From 2571890c842703834296307f22deb2e930602519 Mon Sep 17 00:00:00 2001
From: Christian Kuhn <lolli@schwarzbu.ch>
Date: Sun, 27 Sep 2015 18:21:10 +0200
Subject: [PATCH] [TASK] Extract flex form language handling to compatibility6

Flex form has its own localization handling that exists in parallel
to the record overlay based system. This was introduced together with
the TemplaVoila concept and is almost exclusively used in this context.
For details, the logic is described in the flex form section of
the "localization guide".

With the FormEngine refactoring it is now possible to extract most
parts of this language handling to ext:compatibility6. The patch
moves the current handling classes to compatibility6 and registers
them.

This extraction gives TemplaVoila and maybe other extensions the
opportunity to implement this handling on their own, compatibility6
can be used as a show case how that may be achieved.

As main benefit the classes in FormEngine are significantly
shorter, easier to understand and quite a few options can
be dropped.

Resolves: #70138
Releases: master
Change-Id: Ia2c4b8b329702b895b9183f835423c2d27b7c74a
Reviewed-on: http://review.typo3.org/43601
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
---
 .../Container/FlexFormElementContainer.php    |  178 +-
 .../Form/Container/FlexFormEntryContainer.php |   49 +
 .../Container/FlexFormNoTabsContainer.php     |    7 +-
 .../Form/Container/FlexFormTabsContainer.php  |    9 +-
 .../Form/Container/SingleFieldContainer.php   |    2 +-
 .../Form/FormDataProvider/TcaFlexProcess.php  |  564 ++--
 .../backend/Classes/Form/NodeFactory.php      |    2 +-
 .../FormDataProvider/TcaFlexProcessTest.php   | 1480 +---------
 .../Configuration/FlexForm/FlexFormTools.php  |  412 +++
 .../Container/FlexFormElementContainer.php    |  224 ++
 .../Container/FlexFormEntryContainer.php}     |   14 +-
 .../Container/FlexFormNoTabsContainer.php     |   77 +
 .../Form/Container/FlexFormTabsContainer.php  |  122 +
 .../Form/FormDataProvider/TcaFlexProcess.php  |  715 +++++
 .../FormDataProvider/TcaFlexProcessTest.php   | 2397 +++++++++++++++++
 typo3/sysext/compatibility6/ext_localconf.php |   46 +
 .../Configuration/FlexForm/FlexFormTools.php  |   67 +-
 .../core/Classes/DataHandling/DataHandler.php |    3 +
 .../Configuration/DefaultConfiguration.php    |    1 -
 .../Resource/Driver/LocalDriverFlexForm.xml   |    5 +-
 ...ecation-70138-FlexFormLanguageHandling.rst |   83 +
 .../FlexForms/tt_content_flexform.xml         |    5 +-
 .../sysext/css_styled_content/flexform_ds.xml |    3 -
 .../felogin/Configuration/FlexForms/Login.xml |    3 -
 .../TCA/tx_impexpgroupfiles_item.php          |    3 -
 .../SilentConfigurationUpgradeService.php     |    2 +
 .../mediace/Configuration/FlexForms/media.xml |    3 -
 27 files changed, 4462 insertions(+), 2014 deletions(-)
 create mode 100644 typo3/sysext/backend/Classes/Form/Container/FlexFormEntryContainer.php
 create mode 100644 typo3/sysext/compatibility6/Classes/Configuration/FlexForm/FlexFormTools.php
 create mode 100644 typo3/sysext/compatibility6/Classes/Form/Container/FlexFormElementContainer.php
 rename typo3/sysext/{backend/Classes/Form/Container/FlexFormLanguageContainer.php => compatibility6/Classes/Form/Container/FlexFormEntryContainer.php} (88%)
 create mode 100644 typo3/sysext/compatibility6/Classes/Form/Container/FlexFormNoTabsContainer.php
 create mode 100644 typo3/sysext/compatibility6/Classes/Form/Container/FlexFormTabsContainer.php
 create mode 100644 typo3/sysext/compatibility6/Classes/Form/FormDataProvider/TcaFlexProcess.php
 create mode 100644 typo3/sysext/compatibility6/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Deprecation-70138-FlexFormLanguageHandling.rst

diff --git a/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php b/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php
index 829c64d6d47a..6a9ee0676d08 100644
--- a/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php
+++ b/typo3/sysext/backend/Classes/Form/Container/FlexFormElementContainer.php
@@ -14,13 +14,10 @@ namespace TYPO3\CMS\Backend\Form\Container;
  * The TYPO3 project - inspiring people to share!
  */
 
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Lang\LanguageService;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
-use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 
 /**
@@ -40,16 +37,12 @@ class FlexFormElementContainer extends AbstractContainer {
 	 */
 	public function render() {
 		$table = $this->data['tableName'];
-		$row = $this->data['databaseRow'];
 		$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
 		$flexFormRowData = $this->data['flexFormRowData'];
 		$flexFormFormPrefix = $this->data['flexFormFormPrefix'];
 		$parameterArray = $this->data['parameterArray'];
-		$metaData = $this->data['parameterArray']['fieldConf']['config']['ds']['meta'];
 
 		$languageService = $this->getLanguageService();
-		/** @var IconFactory $iconFactory */
-		$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
 		$resultArray = $this->initializeResultArray();
 		foreach ($flexFormDataStructureArray as $flexFormFieldName => $flexFormFieldArray) {
 			if (
@@ -75,108 +68,77 @@ class FlexFormElementContainer extends AbstractContainer {
 
 				$options = $this->data;
 				$options['flexFormDataStructureArray'] = $flexFormFieldArray['el'];
-				$options['flexFormRowData'] = is_array($flexFormRowData[$flexFormFieldName]['el']) ? $flexFormRowData[$flexFormFieldName]['el'] : array();
+				$options['flexFormRowData'] = isset($flexFormRowData[$flexFormFieldName]['el']) ? $flexFormRowData[$flexFormFieldName]['el'] : [];
 				$options['flexFormSectionType'] = $flexFormFieldName;
 				$options['flexFormSectionTitle'] = $sectionTitle;
 				$options['renderType'] = 'flexFormSectionContainer';
 				$sectionContainerResult = $this->nodeFactory->create($options)->render();
 				$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $sectionContainerResult);
 			} else {
-				if (is_array($metaData) && isset($metaData['langChildren']) && isset($metaData['languagesOnElement'])) {
-					$lkeys = $metaData['languagesOnElement'];
-					array_walk($lkeys, function (&$value) {
-						$value = 'v' . $value;
-					});
-				} else {
-					$lkeys = array('vDEF');
-				}
-				$html = array();
-				foreach ($lkeys as $lkey) {
-					// Set up options for single element
-					$fakeParameterArray = array(
-						'fieldConf' => array(
-							'label' => $languageService->sL(trim($flexFormFieldArray['label'])),
-							'config' => $flexFormFieldArray['config'],
-							'defaultExtras' => $flexFormFieldArray['defaultExtras'],
-							'onChange' => $flexFormFieldArray['onChange'],
-						),
-					);
-
-					$alertMsgOnChange = '';
-					if (
-						$fakeParameterArray['fieldConf']['onChange'] === 'reload'
-						|| !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $GLOBALS['TCA'][$table]['ctrl']['type'] === $flexFormFieldName
-						|| !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $flexFormFieldName)
-					) {
-						if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
-							$alertMsgOnChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });';
-						} else {
-							$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
-						}
-					}
-					$fakeParameterArray['fieldChangeFunc'] = $parameterArray['fieldChangeFunc'];
-					if ($alertMsgOnChange) {
-						$fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
-					}
-
-					$fakeParameterArray['onFocus'] = $parameterArray['onFocus'];
-					$fakeParameterArray['label'] = $parameterArray['label'];
-					$fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']';
-					$fakeParameterArray['itemFormElID'] = $fakeParameterArray['itemFormElName'];
-					if (isset($flexFormRowData[$flexFormFieldName][$lkey])) {
-						$fakeParameterArray['itemFormElValue'] = $flexFormRowData[$flexFormFieldName][$lkey];
+				// Set up options for single element
+				$fakeParameterArray = [
+					'fieldConf' => [
+						'label' => $languageService->sL(trim($flexFormFieldArray['label'])),
+						'config' => $flexFormFieldArray['config'],
+						'defaultExtras' => $flexFormFieldArray['defaultExtras'],
+						'onChange' => $flexFormFieldArray['onChange'],
+					],
+					'fieldChangeFunc' => $parameterArray['fieldChangeFunc'],
+					'onFocus' => $parameterArray['onFocus'],
+					'label' => $parameterArray['label'],
+				];
+
+				$alertMsgOnChange = '';
+				if (
+					$fakeParameterArray['fieldConf']['onChange'] === 'reload'
+					|| !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $GLOBALS['TCA'][$table]['ctrl']['type'] === $flexFormFieldName
+					|| !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $flexFormFieldName)
+				) {
+					if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
+						$alertMsgOnChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });';
 					} else {
-						$fakeParameterArray['itemFormElValue'] = $fakeParameterArray['fieldConf']['config']['default'];
+						$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
 					}
+				}
+				if ($alertMsgOnChange) {
+					$fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
+				}
 
-					$options = $this->data;
-					$options['parameterArray'] = $fakeParameterArray;
-					$options['elementBaseName'] = $this->data['elementBaseName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']';
-
-					if (!empty($flexFormFieldArray['config']['renderType'])) {
-						$options['renderType'] = $flexFormFieldArray['config']['renderType'];
-					} else {
-						// Fallback to type if no renderType is given
-						$options['renderType'] = $flexFormFieldArray['config']['type'];
-					}
-					$childResult = $this->nodeFactory->create($options)->render();
-
-					$theTitle = htmlspecialchars($fakeParameterArray['fieldConf']['label']);
-					$defInfo = array();
-
-					// Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!)
-					$processedTitle = str_replace('\\n', '<br />', $theTitle);
-					// @todo: Similar to the processing within SingleElementContainer ... use it from there?!
-					$html[] = '<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">';
-					$html[] = '<label class="t3js-formengine-label">';
-					if (is_array($metaData) && isset($metaData['langChildren']) && $metaData['langChildren']) {
-						// Find language uid of this iso code
-						$languageUid = 0;
-						$lKeyWithoutV = substr($lkey, 1);
-						if ($lKeyWithoutV !== 'DEF') {
-							foreach ($this->data['systemLanguageRows'] as $systemLanguageRow) {
-								if ($systemLanguageRow['iso'] === $lKeyWithoutV) {
-									$languageUid = $systemLanguageRow['uid'];
-									break;
-								}
-							}
-						}
-						$languageIcon = $iconFactory->getIcon($this->data['systemLanguageRows'][$languageUid]['flagIconIdentifier'], Icon::SIZE_SMALL)->render();
-						$html[] = $languageIcon;
-					}
-					$html[] = BackendUtility::wrapInHelp($parameterArray['_cshKey'], $flexFormFieldName, $processedTitle);
-					$html[] = '</label>';
-					$html[] = '<div class="t3js-formengine-field-item">';
-					$html[] = $childResult['html'];
-					$html[] = implode(LF, $defInfo);
-					$html[] = $this->renderVDEFDiff($flexFormRowData[$flexFormFieldName], $lkey);
-					$html[] = '</div>';
-					$html[] = '</div>';
+				$fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][vDEF]';
+				$fakeParameterArray['itemFormElID'] = $fakeParameterArray['itemFormElName'];
+				if (isset($flexFormRowData[$flexFormFieldName]['vDEF'])) {
+					$fakeParameterArray['itemFormElValue'] = $flexFormRowData[$flexFormFieldName]['vDEF'];
+				} else {
+					$fakeParameterArray['itemFormElValue'] = $fakeParameterArray['fieldConf']['config']['default'];
 				}
 
-				if (!empty($html)) {
-					$resultArray['html'] .= '<div class="form-section">' . implode(LF, $html) . '</div>';
+				$options = $this->data;
+				$options['parameterArray'] = $fakeParameterArray;
+				$options['elementBaseName'] = $this->data['elementBaseName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][vDEF]';
+
+				if (!empty($flexFormFieldArray['config']['renderType'])) {
+					$options['renderType'] = $flexFormFieldArray['config']['renderType'];
+				} else {
+					// Fallback to type if no renderType is given
+					$options['renderType'] = $flexFormFieldArray['config']['type'];
 				}
+				$childResult = $this->nodeFactory->create($options)->render();
+
+				// Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!)
+				$processedTitle = str_replace('\\n', '<br />', htmlspecialchars($fakeParameterArray['fieldConf']['label']));
+				$html = [];
+				$html[] = '<div class="form-section">';
+				$html[] = 	'<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">';
+				$html[] = 		'<label class="t3js-formengine-label">';
+				$html[] = 			BackendUtility::wrapInHelp($parameterArray['_cshKey'], $flexFormFieldName, $processedTitle);
+				$html[] = 		'</label>';
+				$html[] = 		'<div class="t3js-formengine-field-item">';
+				$html[] = 			$childResult['html'];
+				$html[] = 		'</div>';
+				$html[] = 	'</div>';
+				$html[] = '</div>';
+
+				$resultArray['html'] .= implode(LF, $html);
 				$childResult['html'] = '';
 				$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childResult);
 			}
@@ -185,28 +147,6 @@ class FlexFormElementContainer extends AbstractContainer {
 		return $resultArray;
 	}
 
-	/**
-	 * Renders the diff-view of vDEF fields in flex forms
-	 *
-	 * @param array $vArray Record array of the record being edited
-	 * @param string $vDEFkey HTML of the form field. This is what we add the content to.
-	 * @return string Item string returned again, possibly with the original value added to.
-	 */
-	protected function renderVDEFDiff($vArray, $vDEFkey) {
-		$item = NULL;
-		if (
-			$GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && isset($vArray[$vDEFkey . '.vDEFbase'])
-			&& (string)$vArray[$vDEFkey . '.vDEFbase'] !== (string)$vArray['vDEF'][0]
-		) {
-			// Create diff-result:
-			$diffUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Utility\DiffUtility::class);
-			$diffres = $diffUtility->makeDiffDisplay($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF']);
-			$item = '<div class="typo3-TCEforms-diffBox">' . '<div class="typo3-TCEforms-diffBox-header">'
-				. htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.changeInOrig')) . ':</div>' . $diffres . '</div>';
-		}
-		return $item;
-	}
-
 	/**
 	 * @return LanguageService
 	 */
diff --git a/typo3/sysext/backend/Classes/Form/Container/FlexFormEntryContainer.php b/typo3/sysext/backend/Classes/Form/Container/FlexFormEntryContainer.php
new file mode 100644
index 000000000000..e1927547f33d
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Form/Container/FlexFormEntryContainer.php
@@ -0,0 +1,49 @@
+<?php
+namespace TYPO3\CMS\Backend\Form\Container;
+
+/*
+ * 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!
+ */
+
+/**
+ * Entry container to a flex form element. This container is created by
+ * SingleFieldContainer if a type='flex' field is rendered.
+ *
+ * It either forks a FlexFormTabsContainer or a FlexFormNoTabsContainer.
+ */
+class FlexFormEntryContainer extends AbstractContainer {
+
+	/**
+	 * Entry method
+	 *
+	 * @return array As defined in initializeResultArray() of AbstractNode
+	 */
+	public function render() {
+		$flexFormDataStructureArray = $this->data['parameterArray']['fieldConf']['config']['ds'];
+
+		$options = $this->data;
+		$options['flexFormDataStructureArray'] = $flexFormDataStructureArray;
+		$options['flexFormRowData'] = $this->data['parameterArray']['itemFormElValue'];
+		$options['renderType'] = 'flexFormNoTabsContainer';
+
+		// Enable tabs if there is more than one sheet
+		if (count($flexFormDataStructureArray['sheets']) > 1) {
+			$options['renderType'] = 'flexFormTabsContainer';
+		}
+
+		$resultArray = $this->nodeFactory->create($options)->render();
+		$resultArray['requireJsModules'][] = 'TYPO3/CMS/Backend/FormEngineFlexForm';
+
+		return $resultArray;
+	}
+
+}
diff --git a/typo3/sysext/backend/Classes/Form/Container/FlexFormNoTabsContainer.php b/typo3/sysext/backend/Classes/Form/Container/FlexFormNoTabsContainer.php
index 27608a66e85e..46aa94eb4953 100644
--- a/typo3/sysext/backend/Classes/Form/Container/FlexFormNoTabsContainer.php
+++ b/typo3/sysext/backend/Classes/Form/Container/FlexFormNoTabsContainer.php
@@ -19,7 +19,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Handle a flex form that has no tabs.
  *
- * This container is called by FlexFormLanguageContainer if only a default sheet
+ * This container is called by FlexFormEntryContainer if only a default sheet
  * exists. It evaluates the display condition and hands over rendering of single
  * fields to FlexFormElementContainer.
  */
@@ -36,14 +36,13 @@ class FlexFormNoTabsContainer extends AbstractContainer {
 		$fieldName = $this->data['fieldName']; // field name of the flex form field in DB
 		$parameterArray = $this->data['parameterArray'];
 		$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
-		$flexFormCurrentLanguage = $this->data['flexFormCurrentLanguage'];
 		$flexFormRowData = $this->data['flexFormRowData'];
 		$resultArray = $this->initializeResultArray();
 
 		// Flex ds was normalized in flex provider to always have a sheet.
 		// Determine this single sheet name, most often it ends up with sDEF, except if only one sheet was defined
 		$sheetName = array_pop(array_keys($flexFormDataStructureArray['sheets']));
-		$flexFormRowDataSubPart = $flexFormRowData['data'][$sheetName][$flexFormCurrentLanguage];
+		$flexFormRowDataSubPart = $flexFormRowData['data'][$sheetName]['lDEF'] ?: [];
 
 		// That was taken from GeneralUtility::resolveSheetDefInDS - no idea if it is important
 		unset($flexFormDataStructureArray['meta']);
@@ -66,7 +65,7 @@ class FlexFormNoTabsContainer extends AbstractContainer {
 		$options = $this->data;
 		$options['flexFormDataStructureArray'] = $flexFormDataStructureArray['sheets'][$sheetName]['ROOT']['el'];
 		$options['flexFormRowData'] = $flexFormRowDataSubPart;
-		$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][' . $flexFormCurrentLanguage . ']';
+		$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][lDEF]';
 		$options['parameterArray'] = $parameterArray;
 
 		$options['renderType'] = 'flexFormElementContainer';
diff --git a/typo3/sysext/backend/Classes/Form/Container/FlexFormTabsContainer.php b/typo3/sysext/backend/Classes/Form/Container/FlexFormTabsContainer.php
index fc7fd12f6fde..84049d4390d7 100644
--- a/typo3/sysext/backend/Classes/Form/Container/FlexFormTabsContainer.php
+++ b/typo3/sysext/backend/Classes/Form/Container/FlexFormTabsContainer.php
@@ -21,7 +21,7 @@ use TYPO3\CMS\Lang\LanguageService;
 /**
  * Handle flex forms that have tabs (multiple "sheets").
  *
- * This container is called by FlexFormLanguageContainer. It resolves each
+ * This container is called by FlexFormEntryContainer. It resolves each
  * sheet and hands rendering of single sheet content over to FlexFormElementContainer.
  */
 class FlexFormTabsContainer extends AbstractContainer {
@@ -40,17 +40,16 @@ class FlexFormTabsContainer extends AbstractContainer {
 		$fieldName = $this->data['fieldName']; // field name of the flex form field in DB
 		$parameterArray = $this->data['parameterArray'];
 		$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
-		$flexFormCurrentLanguage = $this->data['flexFormCurrentLanguage'];
 		$flexFormRowData = $this->data['flexFormRowData'];
 
-		$tabId = 'TCEFORMS:flexform:' . $this->data['parameterArray']['itemFormElName'] . $flexFormCurrentLanguage;
+		$tabId = 'TCEFORMS:flexform:' . $this->data['parameterArray']['itemFormElName'] . 'lDEF';
 		$tabIdString = $docTemplate->getDynTabMenuId($tabId);
 		$tabCounter = 0;
 
 		$resultArray = $this->initializeResultArray();
 		$tabsContent = array();
 		foreach ($flexFormDataStructureArray['sheets'] as $sheetName => $sheetDataStructure) {
-			$flexFormRowSheetDataSubPart = $flexFormRowData['data'][$sheetName][$flexFormCurrentLanguage];
+			$flexFormRowSheetDataSubPart = $flexFormRowData['data'][$sheetName]['lDEF'] ?: [];
 
 			if (!is_array($sheetDataStructure['ROOT']['el'])) {
 				$resultArray['html'] .= LF . 'No Data Structure ERROR: No [\'ROOT\'][\'el\'] found for sheet "' . $sheetName . '".';
@@ -72,7 +71,7 @@ class FlexFormTabsContainer extends AbstractContainer {
 			$options = $this->data;
 			$options['flexFormDataStructureArray'] = $sheetDataStructure['ROOT']['el'];
 			$options['flexFormRowData'] = $flexFormRowSheetDataSubPart;
-			$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][' . $flexFormCurrentLanguage . ']';
+			$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][lDEF]';
 			$options['parameterArray'] = $parameterArray;
 			// Merge elements of this tab into a single list again and hand over to
 			// palette and single field container to render this group
diff --git a/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php b/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php
index 7be1ab50a075..ce0ad1bcc134 100644
--- a/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php
+++ b/typo3/sysext/backend/Classes/Form/Container/SingleFieldContainer.php
@@ -30,7 +30,7 @@ use TYPO3\CMS\Core\Database\RelationHandler;
  * Container around a "single field".
  *
  * This container is the last one in the chain before processing is handed over to single element classes.
- * If a single field is of type flex or inline, it however creates FlexFormLanguageContainer or InlineControlContainer.
+ * If a single field is of type flex or inline, it however creates FlexFormEntryContainer or InlineControlContainer.
  *
  * The container does various checks and processing for a given single fields, for example it resolves
  * display conditions and the HTML to compare different languages.
diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaFlexProcess.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaFlexProcess.php
index c4874e119117..e02835d24725 100644
--- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaFlexProcess.php
+++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaFlexProcess.php
@@ -48,7 +48,6 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 			$result = $this->modifyOuterDataStructure($result, $fieldName, $pageTsConfigOfFlex);
 			$result = $this->removeExcludeFieldsFromDataStructure($result, $fieldName, $flexIdentifier);
 			$result = $this->removeDisabledFieldsFromDataStructure($result, $fieldName, $pageTsConfigOfFlex);
-			$result = $this->prepareLanguageHandlingInDataValues($result, $fieldName);
 			$result = $this->modifyDataStructureAndDataValuesByFlexFormSegmentGroup($result, $fieldName, $pageTsConfigOfFlex);
 		}
 
@@ -126,13 +125,6 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 	protected function modifyOuterDataStructure(array $result, $fieldName, $pageTsConfig) {
 		$modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
 
-		if (isset($pageTsConfig['langDisable'])) {
-			$modifiedDataStructure['meta']['langDisable'] = $pageTsConfig['langDisable'];
-		}
-		if (isset($pageTsConfig['langChildren'])) {
-			$modifiedDataStructure['meta']['langChildren'] = $pageTsConfig['langChildren'];
-		}
-
 		if (isset($modifiedDataStructure['sheets']) && is_array($modifiedDataStructure['sheets'])) {
 			// Handling multiple sheets
 			foreach ($modifiedDataStructure['sheets'] as $sheetName => $sheetStructure) {
@@ -151,13 +143,6 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 			}
 		}
 
-		$modifiedDataStructure['meta']['langDisable'] = isset($modifiedDataStructure['meta']['langDisable'])
-			? (bool)$modifiedDataStructure['meta']['langDisable']
-			: FALSE;
-		$modifiedDataStructure['meta']['langChildren'] = isset($modifiedDataStructure['meta']['langChildren'])
-			? (bool)$modifiedDataStructure['meta']['langChildren']
-			: FALSE;
-
 		$result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
 
 		return $result;
@@ -205,8 +190,7 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 	}
 
 	/**
-	 * Handle "outer" flex data structure changes like language and sheet
-	 * description. Does not change "TCA" or values of single elements
+	 * Remove fields from data structure that are disabled in pageTsConfig.
 	 *
 	 * @param array $result Result array
 	 * @param string $fieldName Current handle field name
@@ -229,104 +213,6 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 				}
 			}
 		}
-
-		return $result;
-	}
-
-	/**
-	 * Remove data values in languages the user has no access to and add dummy entries
-	 * for languages that are available but do not exist in data values yet.
-	 *
-	 * @param array $result Result array
-	 * @param string $fieldName Current handle field name
-	 * @return array Modified item array
-	 */
-	protected function prepareLanguageHandlingInDataValues(array $result, $fieldName) {
-		$backendUser = $this->getBackendUser();
-		$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
-
-		$langDisabled = $dataStructure['meta']['langDisable'];
-		$langChildren = $dataStructure['meta']['langChildren'];
-
-		// Existing page language overlays are only considered if options.checkPageLanguageOverlay is set in userTs
-		$checkPageLanguageOverlay = FALSE;
-		if (isset($result['userTsConfig']['options.']) && is_array($result['userTsConfig']['options.'])
-			&& array_key_exists('checkPageLanguageOverlay', $result['userTsConfig']['options.'])
-		) {
-			$checkPageLanguageOverlay = (bool)$result['userTsConfig']['options.']['checkPageLanguageOverlay'];
-		}
-
-		$systemLanguageRows = $result['systemLanguageRows'];
-
-		// Contains all language iso code that are valid and user has access to
-		$availableLanguageCodes = [];
-		$defaultCodeWasAdded = FALSE;
-		foreach ($systemLanguageRows as $systemLanguageRow) {
-			$isoCode = $systemLanguageRow['iso'];
-			$isAvailable = TRUE;
-			if ($langDisabled && $isoCode !== 'DEF') {
-				$isAvailable = FALSE;
-			}
-			// @todo: Is it possible a user has no write access to default lang? If so, what to do?
-			if (!$backendUser->checkLanguageAccess($systemLanguageRow['uid'])) {
-				$isAvailable = FALSE;
-			}
-			if ($checkPageLanguageOverlay && $systemLanguageRow['uid'] > 0) {
-				$found = FALSE;
-				foreach ($result['pageLanguageOverlayRows'] as $overlayRow) {
-					if ((int)$overlayRow['sys_language_uid'] === (int)$systemLanguageRow['uid']) {
-						$found = TRUE;
-						break;
-					}
-				}
-				if (!$found) {
-					$isAvailable = FALSE;
-				}
-			}
-			if ($isoCode === 'DEF' && $defaultCodeWasAdded) {
-				$isAvailable = FALSE;
-			}
-			if ($isAvailable) {
-				$availableLanguageCodes[] = $isoCode;
-			}
-			if ($isoCode === 'DEF') {
-				$defaultCodeWasAdded = TRUE;
-			}
-		}
-		// Set the list of available languages in the data structure "meta" section to have it
-		// available for the render engine to iterate over it.
-		$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['availableLanguageCodes'] = $availableLanguageCodes;
-
-		if (!$langChildren) {
-			$allowedLanguageSheetKeys = [];
-			foreach ($availableLanguageCodes as $isoCode) {
-				$allowedLanguageSheetKeys['l' . $isoCode] = [];
-			}
-			$result = $this->setLanguageSheetsInDataValues($result, $fieldName, $allowedLanguageSheetKeys);
-
-			// With $langChildren = 0, values must only contain vDEF prefixed keys
-			$allowedValueLevelLanguageKeys = [];
-			$allowedValueLevelLanguageKeys['vDEF'] = [];
-			$allowedValueLevelLanguageKeys['vDEF.vDEFbase'] = [];
-			// A richtext special
-			$allowedValueLevelLanguageKeys['_TRANSFORM_vDEF.vDEFbase'] = [];
-			$result = $this->setLanguageValueLevelValues($result, $fieldName, $allowedValueLevelLanguageKeys);
-		} else {
-			// langChildren is set - only lDEF as sheet language is allowed, but more fields on value field level
-			$allowedLanguageSheetKeys = [
-				'lDEF' => [],
-			];
-			$result = $this->setLanguageSheetsInDataValues($result, $fieldName, $allowedLanguageSheetKeys);
-
-			$allowedValueLevelLanguageKeys = [];
-			foreach ($availableLanguageCodes as $isoCode) {
-				$allowedValueLevelLanguageKeys['v' . $isoCode] = [];
-				$allowedValueLevelLanguageKeys['v' . $isoCode . '.vDEFbase'] = [];
-				$allowedValueLevelLanguageKeys['_TRANSFORM_v' . $isoCode . '.vDEFbase'] = [];
-			}
-			$result = $this->setLanguageValueLevelValues($result, $fieldName, $allowedValueLevelLanguageKeys);
-		}
-
 		return $result;
 	}
 
@@ -349,18 +235,6 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 		$dataValues = $result['databaseRow'][$fieldName];
 		$tableName = $result['tableName'];
 
-		$availableLanguageCodes = $result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['availableLanguageCodes'];
-		if ($dataStructure['meta']['langChildren']) {
-			$languagesOnSheetLevel = [ 'DEF' ];
-			$languagesOnElementLevel = $availableLanguageCodes;
-		} else {
-			$languagesOnSheetLevel = $availableLanguageCodes;
-			$languagesOnElementLevel = [ 'DEF' ];
-		}
-
-		$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['languagesOnSheetLevel'] = $languagesOnSheetLevel;
-		$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['languagesOnElement'] = $languagesOnElementLevel;
-
 		if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
 			return $result;
 		}
@@ -382,194 +256,182 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 				$pageTsConfigMerged['TCEFORM.'][$tableName . '.'] = $pageTsConfig[$dataStructureSheetName . '.'];
 			}
 
-			foreach ($languagesOnSheetLevel as $isoSheetLevel) {
-				$langSheetLevel = 'l' . $isoSheetLevel;
-				foreach ($dataStructureSheetElements as $dataStructureSheetElementName => $dataStructureSheetElementDefinition) {
-					if (isset($dataStructureSheetElementDefinition['type']) && $dataStructureSheetElementDefinition['type'] === 'array'
-						&& isset($dataStructureSheetElementDefinition['section']) && $dataStructureSheetElementDefinition['section'] === '1'
+			foreach ($dataStructureSheetElements as $dataStructureSheetElementName => $dataStructureSheetElementDefinition) {
+				if (isset($dataStructureSheetElementDefinition['type']) && $dataStructureSheetElementDefinition['type'] === 'array'
+					&& isset($dataStructureSheetElementDefinition['section']) && $dataStructureSheetElementDefinition['section'] === '1'
+				) {
+					// A section
+
+					// Existing section container elements
+					if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'])
+						&& is_array($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'])
 					) {
-						// A section
-
-						// Existing section container elements
-						if (isset($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'])
-							&& is_array($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'])
-						) {
-							$containerArray = $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'];
-							foreach ($containerArray as $aContainerNumber => $aContainerArray) {
-								if (is_array($aContainerArray)) {
-									foreach ($aContainerArray as $aContainerName => $aContainerElementArray) {
-										if ($aContainerName === '_TOGGLE') {
-											// Don't handle internal toggle state field
-											continue;
-										}
-										if (!isset($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName])) {
-											// Container not defined in ds
-											continue;
+						$containerArray = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el'];
+						foreach ($containerArray as $aContainerNumber => $aContainerArray) {
+							if (is_array($aContainerArray)) {
+								foreach ($aContainerArray as $aContainerName => $aContainerElementArray) {
+									if ($aContainerName === '_TOGGLE') {
+										// Don't handle internal toggle state field
+										continue;
+									}
+									if (!isset($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName])) {
+										// Container not defined in ds
+										continue;
+									}
+									foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName]['el'] as $singleFieldName => $singleFieldConfiguration) {
+										// $singleFieldValueArray = ['data']['sSections']['lDEF']['section_1']['el']['1']['container_1']['el']['element_1']
+										$singleFieldValueArray = [];
+										if (isset($aContainerElementArray['el'][$singleFieldName])
+											&& is_array($aContainerElementArray['el'][$singleFieldName])
+										) {
+											$singleFieldValueArray = $aContainerElementArray['el'][$singleFieldName];
 										}
-										foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName]['el'] as $singleFieldName => $singleFieldConfiguration) {
-											// $singleFieldValueArray = ['data']['sSections']['lDEF']['section_1']['el']['1']['container_1']['el']['element_1']
-											$singleFieldValueArray = [];
-											if (isset($aContainerElementArray['el'][$singleFieldName])
-												&& is_array($aContainerElementArray['el'][$singleFieldName])
-											) {
-												$singleFieldValueArray = $aContainerElementArray['el'][$singleFieldName];
-											}
-											foreach ($languagesOnElementLevel as $isoElementLevel) {
-												$langElementLevel = 'v' . $isoElementLevel;
-												$valueArray = [
-													'uid' => $result['databaseRow']['uid'],
-												];
-												$command = 'new';
-												if (array_key_exists($langElementLevel, $singleFieldValueArray)) {
-													$command = 'edit';
-													$valueArray[$singleFieldName] = $singleFieldValueArray[$langElementLevel];
-												}
-												$inputToFlexFormSegment = [
-													'tableName' => $result['tableName'],
-													'command' => $command,
-													// It is currently not possible to have pageTsConfig for section container
-													'pageTsConfigMerged' => [],
-													'databaseRow' => $valueArray,
-													'vanillaTableTca' => [
-														'ctrl' => [],
-														'columns' => [
-															$singleFieldName => $singleFieldConfiguration,
-														],
-													],
-													'processedTca' => [
-														'ctrl' => [],
-														'columns' => [
-															$singleFieldName => $singleFieldConfiguration,
-														],
-													],
-												];
-												$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
-												// Set data value result
-												if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
-													$result['databaseRow'][$fieldName]
-													['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el']
-													[$aContainerNumber][$aContainerName]['el']
-													[$singleFieldName][$langElementLevel]
-														= $flexSegmentResult['databaseRow'][$singleFieldName];
-												}
-												// Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
-												// handling below will set it again.
-												$result['processedTca']['columns'][$fieldName]['config']['ds']
-												['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
-												[$aContainerName]['el'][$singleFieldName]
-													= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
-											}
+										$valueArray = [
+											'uid' => $result['databaseRow']['uid'],
+										];
+										$command = 'new';
+										if (array_key_exists('vDEF', $singleFieldValueArray)) {
+											$command = 'edit';
+											$valueArray[$singleFieldName] = $singleFieldValueArray['vDEF'];
 										}
-									}
-								}
-							}
-						} // End of existing data value handling
-
-						// Prepare "fresh" row for every possible container
-						if (isset($dataStructureSheetElements[$dataStructureSheetElementName]['el']) && is_array($dataStructureSheetElements[$dataStructureSheetElementName]['el'])) {
-							foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'] as $possibleContainerName => $possibleContainerConfiguration) {
-								if (isset($possibleContainerConfiguration['el']) && is_array($possibleContainerConfiguration['el'])) {
-									// Initialize result data array templateRows
-									$result['databaseRow'][$fieldName]
-									['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['templateRows']
-									[$possibleContainerName]['el']
-										= [];
-									foreach ($possibleContainerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
-										foreach ($languagesOnElementLevel as $isoElementLevel) {
-											$langElementLevel = 'v' . $isoElementLevel;
-											$inputToFlexFormSegment = [
-												'tableName' => $result['tableName'],
-												'command' => 'new',
-												'pageTsConfigMerged' => [],
-												'databaseRow' => [
-													'uid' => $result['databaseRow']['uid'],
+										$inputToFlexFormSegment = [
+											'tableName' => $result['tableName'],
+											'command' => $command,
+											// It is currently not possible to have pageTsConfig for section container
+											'pageTsConfigMerged' => [],
+											'databaseRow' => $valueArray,
+											'vanillaTableTca' => [
+												'ctrl' => [],
+												'columns' => [
+													$singleFieldName => $singleFieldConfiguration,
 												],
-												'vanillaTableTca' => [
-													'ctrl' => [],
-													'columns' => [
-														$singleFieldName => $singleFieldConfiguration,
-													],
+											],
+											'processedTca' => [
+												'ctrl' => [],
+												'columns' => [
+													$singleFieldName => $singleFieldConfiguration,
 												],
-												'processedTca' => [
-													'ctrl' => [],
-													'columns' => [
-														$singleFieldName => $singleFieldConfiguration,
-													],
-												],
-											];
-											$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
-											if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
-												$result['databaseRow'][$fieldName]
-												['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['templateRows']
-												[$possibleContainerName]['el'][$singleFieldName][$langElementLevel]
-												 = $flexSegmentResult['databaseRow'][$singleFieldName];
-											}
-											$result['processedTca']['columns'][$fieldName]['config']['ds']
-											['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
-											[$possibleContainerName]['el'][$singleFieldName]
-												= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
+											],
+										];
+										$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
+										// Set data value result
+										if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
+											$result['databaseRow'][$fieldName]
+											['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['el']
+											[$aContainerNumber][$aContainerName]['el']
+											[$singleFieldName]['vDEF']
+												= $flexSegmentResult['databaseRow'][$singleFieldName];
 										}
+										// Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
+										// handling below will set it again.
+										$result['processedTca']['columns'][$fieldName]['config']['ds']
+										['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
+										[$aContainerName]['el'][$singleFieldName]
+											= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
 									}
 								}
 							}
-						} // End of preparation for each possible container
-
-					// type without section is not ok
-					} elseif (isset($dataStructureSheetElementDefinition['type']) || isset($dataStructureSheetElementDefinition['section'])) {
-						throw new \UnexpectedValueException(
-							'Broken data structure on field name ' . $fieldName . '. section without type or vice versa is not allowed',
-							1440685208
-						);
-
-					// A "normal" TCA element
-					} else {
-						foreach ($languagesOnElementLevel as $isoElementLevel) {
-							$langElementLevel = 'v' . $isoElementLevel;
-							$valueArray = [
-								// uid of "parent" is given down for inline elements to resolve correctly
-								'uid' => $result['databaseRow']['uid'],
-							];
-							$command = 'new';
-							if (isset($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName])
-								&& array_key_exists($langElementLevel, $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName])
-							) {
-								$command = 'edit';
-								$valueArray[$dataStructureSheetElementName] = $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName][$langElementLevel];
-							}
-							$inputToFlexFormSegment = [
-								// tablename of "parent" is given down for inline elements to resolve correctly
-								'tableName' => $result['tableName'],
-								'command' => $command,
-								'pageTsConfigMerged' => $pageTsConfigMerged,
-								'databaseRow' => $valueArray,
-								'vanillaTableTca' => [
-									'ctrl' => [],
-									'columns' => [
-										$dataStructureSheetElementName => $dataStructureSheetElementDefinition,
-									],
-								],
-								'processedTca' => [
-									'ctrl' => [],
-									'columns' => [
-										$dataStructureSheetElementName => $dataStructureSheetElementDefinition,
-									],
-								],
-							];
-							$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
-							// Set data value result
-							if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
+						}
+					} // End of existing data value handling
+
+					// Prepare "fresh" row for every possible container
+					if (isset($dataStructureSheetElements[$dataStructureSheetElementName]['el']) && is_array($dataStructureSheetElements[$dataStructureSheetElementName]['el'])) {
+						foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'] as $possibleContainerName => $possibleContainerConfiguration) {
+							if (isset($possibleContainerConfiguration['el']) && is_array($possibleContainerConfiguration['el'])) {
+								// Initialize result data array templateRows
 								$result['databaseRow'][$fieldName]
-								['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName][$langElementLevel]
-									= $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
+								['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['templateRows']
+								[$possibleContainerName]['el']
+									= [];
+								foreach ($possibleContainerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
+									$inputToFlexFormSegment = [
+										'tableName' => $result['tableName'],
+										'command' => 'new',
+										'pageTsConfigMerged' => [],
+										'databaseRow' => [
+											'uid' => $result['databaseRow']['uid'],
+										],
+										'vanillaTableTca' => [
+											'ctrl' => [],
+											'columns' => [
+												$singleFieldName => $singleFieldConfiguration,
+											],
+										],
+										'processedTca' => [
+											'ctrl' => [],
+											'columns' => [
+												$singleFieldName => $singleFieldConfiguration,
+											],
+										],
+									];
+									$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
+									if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
+										$result['databaseRow'][$fieldName]
+										['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['templateRows']
+										[$possibleContainerName]['el'][$singleFieldName]['vDEF']
+										 = $flexSegmentResult['databaseRow'][$singleFieldName];
+									}
+									$result['processedTca']['columns'][$fieldName]['config']['ds']
+									['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
+									[$possibleContainerName]['el'][$singleFieldName]
+										= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
+								}
 							}
-							// Set TCA structure result
-							$result['processedTca']['columns'][$fieldName]['config']['ds']
-							['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
-								= $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
 						}
-					} // End of single element handling
+					} // End of preparation for each possible container
+
+				// type without section is not ok
+				} elseif (isset($dataStructureSheetElementDefinition['type']) || isset($dataStructureSheetElementDefinition['section'])) {
+					throw new \UnexpectedValueException(
+						'Broken data structure on field name ' . $fieldName . '. section without type or vice versa is not allowed',
+						1440685208
+					);
+
+				// A "normal" TCA element
+				} else {
+					$valueArray = [
+						// uid of "parent" is given down for inline elements to resolve correctly
+						'uid' => $result['databaseRow']['uid'],
+					];
+					$command = 'new';
+					if (isset($dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName])
+						&& array_key_exists('vDEF', $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName])
+					) {
+						$command = 'edit';
+						$valueArray[$dataStructureSheetElementName] = $dataValues['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF'];
+					}
+					$inputToFlexFormSegment = [
+						// tablename of "parent" is given down for inline elements to resolve correctly
+						'tableName' => $result['tableName'],
+						'command' => $command,
+						'pageTsConfigMerged' => $pageTsConfigMerged,
+						'databaseRow' => $valueArray,
+						'vanillaTableTca' => [
+							'ctrl' => [],
+							'columns' => [
+								$dataStructureSheetElementName => $dataStructureSheetElementDefinition,
+							],
+						],
+						'processedTca' => [
+							'ctrl' => [],
+							'columns' => [
+								$dataStructureSheetElementName => $dataStructureSheetElementDefinition,
+							],
+						],
+					];
+					$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
+					// Set data value result
+					if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
+						$result['databaseRow'][$fieldName]
+						['data'][$dataStructureSheetName]['lDEF'][$dataStructureSheetElementName]['vDEF']
+							= $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
+					}
+					// Set TCA structure result
+					$result['processedTca']['columns'][$fieldName]['config']['ds']
+					['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
+						= $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
+				} // End of single element handling
 
-				}
 			}
 		}
 
@@ -606,104 +468,6 @@ class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInt
 		return $dataStructure;
 	}
 
-	/**
-	 * Add new sheet languages not yet in data values and remove invalid ones
-	 *
-	 * databaseRow['aFlex']['data']['sDEF'] = array('lDEF', 'lNotAllowed');
-	 * allowedLanguageKeys = array('lDEF', 'lNEW')
-	 * -> databaseRow['aFlex']['data']['sDEF'] = array('lDEF', 'lNEW');
-	 *
-	 * @param array $result Result array
-	 * @param string $fieldName Current handle field name
-	 * @param array $allowedKeys List of allowed keys
-	 * @return array Modified result
-	 */
-	protected function setLanguageSheetsInDataValues(array $result, $fieldName, array $allowedKeys) {
-		$valueArray = [];
-		if (isset($result['databaseRow'][$fieldName]['data']) && is_array($result['databaseRow'][$fieldName]['data'])) {
-			$valueArray = $result['databaseRow'][$fieldName]['data'];
-		}
-		foreach ($valueArray as $sheetName => $sheetLanguages) {
-			// Add iso code with empty array if it does not yet exist in data
-			// and remove codes from data that do not exist in $allowed
-			$result['databaseRow'][$fieldName]['data'][$sheetName]
-				= array_intersect_key(array_merge($allowedKeys, $sheetLanguages), $allowedKeys);
-		}
-		return $result;
-	}
-
-	/**
-	 * Remove invalid keys from data value array the user has no access to
-	 * or that were removed or similar to prevent any rendering of this stuff
-	 *
-	 * Handles this for "normal" fields and also for section container element values.
-	 *
-	 * @param array $result Result array
-	 * @param string $fieldName Current handle field name
-	 * @param array $allowedKeys List of allowed keys
-	 * @return array Modified result
-	 */
-	protected function setLanguageValueLevelValues(array $result, $fieldName, $allowedKeys) {
-		$valueArray = [];
-		if (isset($result['databaseRow'][$fieldName]['data']) && is_array($result['databaseRow'][$fieldName]['data'])) {
-			$valueArray = $result['databaseRow'][$fieldName]['data'];
-		}
-		foreach ($valueArray as $sheetName => $sheetLanguages) {
-			if (!is_array($sheetLanguages)) {
-				continue;
-			}
-			foreach ($sheetLanguages as $languageName => $languageFields) {
-				if (!is_array($languageFields)) {
-					continue;
-				}
-				foreach ($languageFields as $flexFieldName => $fieldValues) {
-					if (!is_array($fieldValues)) {
-						continue;
-					}
-					$allowedSingleValues = [];
-					foreach ($fieldValues as $fieldValueName => $fieldValueValue) {
-						if (is_array($fieldValueValue) && $fieldValueName === 'el') {
-							// A section container
-							foreach ($fieldValueValue as $sectionNumber => $sectionElementArray) {
-								if (is_array($sectionElementArray)) {
-									$allowedSingleValues['el'][$sectionNumber] = [];
-									foreach ($sectionElementArray as $sectionElementName => $containerElementArray) {
-										if (isset($containerElementArray['el']) && is_array($containerElementArray['el']) && !empty($containerElementArray['el'])) {
-											foreach ($containerElementArray['el'] as $aContainerElementName => $aContainerElementValues) {
-												if (is_array($aContainerElementValues)) {
-													foreach ($aContainerElementValues as $aContainerElementValueKey => $aContainerElementValueValue) {
-														if (array_key_exists($aContainerElementValueKey, $allowedKeys)) {
-															$allowedSingleValues['el'][$sectionNumber][$sectionElementName]
-															['el'][$aContainerElementName][$aContainerElementValueKey] = $aContainerElementValueValue;
-														}
-													}
-												} else {
-													$allowedSingleValues['el'][$sectionNumber][$sectionElementName]['el']
-													[$aContainerElementName] = $aContainerElementValues;
-												}
-											}
-										} else {
-											$allowedSingleValues['el'][$sectionNumber][$sectionElementName] = $containerElementArray;
-										}
-									}
-								} else {
-									$allowedSingleValues = $sectionElementArray;
-								}
-							}
-						} else {
-							// "normal" value field
-							if (array_key_exists($fieldValueName, $allowedKeys)) {
-								$allowedSingleValues[$fieldValueName] = $fieldValueValue;
-							}
-						}
-					}
-					$result['databaseRow'][$fieldName]['data'][$sheetName][$languageName][$flexFieldName] = $allowedSingleValues;
-				}
-			}
-		}
-		return $result;
-	}
-
 	/**
 	 * @return BackendUserAuthentication
 	 */
diff --git a/typo3/sysext/backend/Classes/Form/NodeFactory.php b/typo3/sysext/backend/Classes/Form/NodeFactory.php
index 28b18955bbca..663bb83fda0a 100644
--- a/typo3/sysext/backend/Classes/Form/NodeFactory.php
+++ b/typo3/sysext/backend/Classes/Form/NodeFactory.php
@@ -29,7 +29,7 @@ class NodeFactory {
 	 * @var array
 	 */
 	protected $nodeTypes = array(
-		'flex' => Container\FlexFormLanguageContainer::class,
+		'flex' => Container\FlexFormEntryContainer::class,
 		'flexFormContainerContainer' => Container\FlexFormContainerContainer::class,
 		'flexFormElementContainer' => Container\FlexFormElementContainer::class,
 		'flexFormNoTabsContainer' => Container\FlexFormNoTabsContainer::class,
diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php
index 652137706376..2ec5a69e194f 100644
--- a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php
+++ b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php
@@ -17,11 +17,8 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
 use Prophecy\Argument;
 use Prophecy\Prophecy\ObjectProphecy;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Cache\CacheManager;
-use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Tests\UnitTestCase;
 use TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexProcess;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Lang\LanguageService;
 
 /**
@@ -53,122 +50,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 		$this->subject = new TcaFlexProcess();
 	}
 
-	/**
-	 * @test
-	 */
-	public function addDataOverwritesDataStructureLangDisableIfSetViaPageTsConfig() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'sheets' => [
-									'sDEF' => [
-										'ROOT' => [],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-			'pageTsConfigMerged' => [
-				'TCEFORM.' => [
-					'aTable.' => [
-						'aField.' => [
-							'aFlex.' => [
-								'langDisable' => 1,
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [],
-			'langDisable' => TRUE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			],
-		];
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataOverwritesDataStructureLangChildrenIfSetViaPageTsConfig() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'sheets' => [
-									'sDEF' => [
-										'ROOT' => [],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-			'pageTsConfigMerged' => [
-				'TCEFORM.' => [
-					'aTable.' => [
-						'aField.' => [
-							'aFlex.' => [
-								'langChildren' => FALSE,
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [],
-			'langDisable' => FALSE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
-		];
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
 	/**
 	 * @test
 	 */
@@ -178,11 +59,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -227,15 +106,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [],
 		];
 
@@ -251,11 +121,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -300,15 +168,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'aSheet' => [
 					'ROOT' => [
@@ -339,11 +198,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -388,15 +245,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'aSheet' => [
 					'ROOT' => [
@@ -427,11 +275,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -476,15 +322,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'aSheet' => [
 					'ROOT' => [
@@ -515,11 +352,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -564,15 +399,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'sDEF' => [
 					'ROOT' => [
@@ -603,11 +429,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -644,15 +468,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'sDEF' => [
 					'ROOT' => [
@@ -675,11 +490,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -716,15 +529,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'sDEF' => [
 					'ROOT' => [
@@ -755,11 +559,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -796,15 +598,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'sDEF' => [
 					'ROOT' => [
@@ -835,11 +628,9 @@ class TcaFlexProcessTest extends UnitTestCase {
 			'databaseRow' => [
 				'aField' => [
 					'data' => [],
-					'meta' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -886,15 +677,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 
 		$expected = $input;
 		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
 			'sheets' => [
 				'sDEF' => [
 					'ROOT' => [
@@ -911,86 +693,15 @@ class TcaFlexProcessTest extends UnitTestCase {
 	/**
 	 * @test
 	 */
-	public function addDataCleansLanguageDisabledDataValues() {
+	public function addDataHandlesPageTsConfigSettingsOfSingleFlexField() {
 		$input = [
 			'tableName' => 'aTable',
 			'databaseRow' => [
 				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [
-								'input_1' => [
-									'vDEF' => 'input1 text',
-									'vDEF.vDEFbase' => 'base',
-									'_TRANSFORM_vDEF.vDEFbase' => 'transform',
-									'vRemoveMe' => 'removeMe',
-									'vRemoveMe.vDEFbase' => 'removeMe',
-									'_TRANSFORM_vRemoveMe.vDEFbase' => 'removeMe',
-								],
-								'section_1' => [
-									'el' => [
-										'1' => [
-											'container_1' => [
-												'el' => [
-													'input_2' => [
-														'vDEF' => 'input2 text',
-														'vRemoveMe' => 'removeMe',
-													]
-												],
-											],
-										],
-									],
-								],
-								'invalid1' => 'keepMe',
-								'invalid2' => [
-									'el' => [
-										'1' => [
-											'keepMe',
-										],
-									],
-								],
-								'invalid3' => [
-									'el' => [
-										'1' => [
-											'container_2' => 'keepMe',
-										],
-									],
-								],
-								'invalid4' => [
-									'el' => [
-										'1' => [
-											'container_2' => [
-												'el' => 'keepMe',
-											],
-										],
-									],
-								],
-								'invalid5' => [
-									'el' => [
-										'1' => [
-											'container_2' => [
-												'el' => [
-													'field' => 'keepMe',
-												],
-											],
-										],
-									],
-								],
-							],
-							'lRemoveMe' => [],
-						],
-					],
-					'meta' => [],
+					'data' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'title' => 'aLanguageTitle',
-					'iso' => 'DEF',
-				],
-			],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -998,10 +709,44 @@ class TcaFlexProcessTest extends UnitTestCase {
 							'type' => 'flex',
 							'ds_pointerField' => 'pointerField',
 							'ds' => [
-								'meta' => [
-									'langDisable' => 1,
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'radio',
+														'items' => [
+															0 => [
+																0 => 'aLabel',
+																1 => 'aValue',
+															],
+														],
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'sDEF.' => [
+									'aFlexField.' => [
+										'altLabels.' => [
+											'0' => 'labelOverride',
+										],
+									],
 								],
-								'sheets' => [],
 							],
 						],
 					],
@@ -1009,79 +754,58 @@ class TcaFlexProcessTest extends UnitTestCase {
 			],
 		];
 
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [],
+		];
+
+		/** @var LanguageService|ObjectProphecy $languageService */
+		$languageService = $this->prophesize(LanguageService::class);
+		$GLOBALS['LANG'] = $languageService->reveal();
+		$languageService->sL(Argument::cetera())->willReturnArgument(0);
+
 		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
 
 		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-			],
-			'langDisable' => TRUE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'sheets' => [
+				'sDEF' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'radio',
+									'items' => [
+										0 => [
+											0 => 'labelOverride',
+											1 => 'aValue',
+										],
+									],
+								],
+							],
+						],
+					],
+				],
 			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
 		];
 
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lRemoveMe']);
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vRemoveMe']);
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vRemoveMe.vDEFbase']);
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['_TRANSFORM_vRemoveMe.vDEFbase']);
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['input_2']['vRemoveMe']);
-
 		$this->assertEquals($expected, $this->subject->addData($input));
 	}
 
 	/**
 	 * @test
 	 */
-	public function addDataRemovesDataValuesIfUserHasNoAccess() {
+	public function addDataSetsDefaultValueFromFlexTcaForField() {
 		$input = [
 			'tableName' => 'aTable',
 			'databaseRow' => [
 				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [
-								'input_1' => [
-									'vDEF' => 'input1 text',
-								],
-								'section_1' => [
-									'el' => [
-										'1' => [
-											'container_1' => [
-												'el' => [
-													'input_2' => [
-														'vDEF' => 'input2 text',
-														'vNoAccess' => 'removeMe',
-													]
-												],
-											],
-										],
-									],
-								],
-							],
-							'lNoAccess' => [],
-						],
-					],
-					'meta' => [],
+					'data' => [],
 				],
 				'pointerField' => 'aFlex',
 			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'NoAccess',
-				],
-			],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -1089,720 +813,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 							'type' => 'flex',
 							'ds_pointerField' => 'pointerField',
 							'ds' => [
-								'meta' => [
-									'langDisable' => 0,
-								],
-								'sheets' => [],
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(FALSE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
-		];
-
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lNoAccess']);
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['input_2']['vNoAccess']);
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataAddsNewLanguageDataValues() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [
-								'input_1' => [
-									'vDEF' => 'input1 text',
-								],
-							],
-						],
-					],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'meta' => [
-									'langDisable' => 0,
-								],
-								'sheets' => [],
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(TRUE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
-		];
-
-		$expected['databaseRow']['aField']['data']['sDEF']['lEN'] = [];
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataRemovesDataValuesIfPageOverlayCheckIsEnabled() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [],
-							'lEN' => [],
-							'lNoOverlay' => [],
-						],
-					],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-				2 => [
-					'uid' => 2,
-					'iso' => 'NoOverlay',
-				],
-			],
-			'userTsConfig' => [
-				'options.' => [
-					'checkPageLanguageOverlay' => '1',
-				],
-			],
-			'pageLanguageOverlayRows' => [
-				0 => [
-					'uid' => 1,
-					'sys_language_uid' => 1,
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'meta' => [
-									'langDisable' => 0,
-								],
-								'sheets' => [],
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('2')->shouldBeCalled()->willReturn(TRUE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
-		];
-
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lNoOverlay']);
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataRemovesLanguageDataValuesIfUserHasNoAccessWithLangChildren() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [
-								'input_1' => [
-									'vDEF' => 'input1 text',
-									'vNoAccess' => 'removeMe',
-								],
-								'section_1' => [
-									'el' => [
-										'1' => [
-											'container_1' => [
-												'el' => [
-													'input_2' => [
-														'vDEF' => 'input2 text',
-														'vNoAccess' => 'removeMe',
-													]
-												],
-											],
-										],
-									],
-								],
-							],
-							'lNoAccess' => [],
-						],
-					],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'NoAccess',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'meta' => [
-									'langDisable' => 0,
-									'langChildren' => 1,
-								],
-								'sheets' => [],
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(FALSE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => TRUE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
-		];
-
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lNoAccess']);
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vNoAccess']);
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['input_2']['vNoAccess']);
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataRemovesDataValuesIfPageOverlayCheckIsEnabledWithLangChildren() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [
-								'input_1' => [
-									'vDEF' => 'input1 text',
-									'vEN' => 'input1 en text',
-									'vNoOverlay' => 'removeMe',
-								],
-							],
-						],
-					],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-				2 => [
-					'uid' => 2,
-					'iso' => 'NoOverlay',
-				],
-			],
-			'userTsConfig' => [
-				'options.' => [
-					'checkPageLanguageOverlay' => '1',
-				],
-			],
-			'pageLanguageOverlayRows' => [
-				0 => [
-					'uid' => 1,
-					'sys_language_uid' => 1,
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'meta' => [
-									'langDisable' => 0,
-									'langChildren' => 1,
-								],
-								'sheets' => [],
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess('2')->shouldBeCalled()->willReturn(TRUE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => TRUE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-				1 => 'EN',
-			]
-		];
-
-		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vNoOverlay']);
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataHandlesPageTsConfigSettingsOfSingleFlexField() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'meta' => [
-									'langDisable' => 0,
-									'langChildren' => 0,
-								],
-								'sheets' => [
-									'sDEF' => [
-										'ROOT' => [
-											'type' => 'array',
-											'el' => [
-												'aFlexField' => [
-													'label' => 'aFlexFieldLabel',
-													'config' => [
-														'type' => 'radio',
-														'items' => [
-															0 => [
-																0 => 'aLabel',
-																1 => 'aValue',
-															],
-														],
-													],
-												],
-											],
-										],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-			'pageTsConfigMerged' => [
-				'TCEFORM.' => [
-					'aTable.' => [
-						'aField.' => [
-							'aFlex.' => [
-								'sDEF.' => [
-									'aFlexField.' => [
-										'altLabels.' => [
-											'0' => 'labelOverride',
-										],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
-			\TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [],
-		];
-
-		/** @var LanguageService|ObjectProphecy $languageService */
-		$languageService = $this->prophesize(LanguageService::class);
-		$GLOBALS['LANG'] = $languageService->reveal();
-		$languageService->sL(Argument::cetera())->willReturnArgument(0);
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds'] = [
-			'meta' => [
-				'availableLanguageCodes' => [
-					0 => 'DEF',
-				],
-				'langDisable' => FALSE,
-				'langChildren' => FALSE,
-				'languagesOnSheetLevel' => [
-					0 => 'DEF',
-				],
-				'languagesOnElement' => [
-					0 => 'DEF',
-				]
-			],
-			'sheets' => [
-				'sDEF' => [
-					'ROOT' => [
-						'type' => 'array',
-						'el' => [
-							'aFlexField' => [
-								'label' => 'aFlexFieldLabel',
-								'config' => [
-									'type' => 'radio',
-									'items' => [
-										0 => [
-											0 => 'labelOverride',
-											1 => 'aValue',
-										],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-		];
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataSetsDefaultValueFromFlexTcaForField() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => [
-								'sheets' => [
-									'sDEF' => [
-										'ROOT' => [
-											'type' => 'array',
-											'el' => [
-												'aFlexField' => [
-													'label' => 'aFlexFieldLabel',
-													'config' => [
-														'type' => 'input',
-														'default' => 'defaultValue',
-													],
-												],
-											],
-										],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-			'pageTsConfigMerged' => [],
-		];
-
-		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
-			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
-		];
-
-		/** @var LanguageService|ObjectProphecy $languageService */
-		$languageService = $this->prophesize(LanguageService::class);
-		$GLOBALS['LANG'] = $languageService->reveal();
-		$languageService->sL(Argument::cetera())->willReturnArgument(0);
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
-		];
-
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vDEF'] = 'defaultValue';
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataSetsDefaultValueFromFlexTcaForFieldInLocalizedSheet() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [],
-					'meta' => [],
-				],
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds' => [
-								'sheets' => [
-									'sDEF' => [
-										'ROOT' => [
-											'type' => 'array',
-											'el' => [
-												'aFlexField' => [
-													'label' => 'aFlexFieldLabel',
-													'config' => [
-														'type' => 'input',
-														'default' => 'defaultValue',
-													],
-												],
-											],
-										],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-			'pageTsConfigMerged' => [],
-		];
-
-		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
-			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
-		];
-
-		/** @var LanguageService|ObjectProphecy $languageService */
-		$languageService = $this->prophesize(LanguageService::class);
-		$GLOBALS['LANG'] = $languageService->reveal();
-		$languageService->sL(Argument::cetera())->willReturnArgument(0);
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF'
-			]
-		];
-
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vDEF'] = 'defaultValue';
-		$expected['databaseRow']['aField']['data']['sDEF']['lEN']['aFlexField']['vDEF'] = 'defaultValue';
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataSetsDefaultValueFromFlexTcaForFieldInLocalizedSheetWithLangChildren() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [],
-					'meta' => [],
-				],
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds' => [
-								'meta' => [
-									'langChildren' => 1,
-								],
 								'sheets' => [
 									'sDEF' => [
 										'ROOT' => [
@@ -1840,24 +850,7 @@ class TcaFlexProcessTest extends UnitTestCase {
 		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
 
 		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => TRUE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-				1 => 'EN'
-			]
-		];
-
 		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vDEF'] = 'defaultValue';
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vEN'] = 'defaultValue';
 
 		$this->assertEquals($expected, $this->subject->addData($input));
 	}
@@ -1874,12 +867,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 					'meta' => [],
 				],
 			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-			],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -1926,12 +913,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 					'meta' => [],
 				],
 			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-			],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -1969,7 +950,7 @@ class TcaFlexProcessTest extends UnitTestCase {
 	/**
 	 * @test
 	 */
-	public function addDataSetsValuesAndStructureForSectionContainerElementsNoLangChildren() {
+	public function addDataSetsValuesAndStructureForSectionContainerElements() {
 		$input = [
 			'tableName' => 'aTable',
 			'databaseRow' => [
@@ -2015,16 +996,6 @@ class TcaFlexProcessTest extends UnitTestCase {
 					'meta' => [],
 				],
 			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-			],
 			'processedTca' => [
 				'columns' => [
 					'aField' => [
@@ -2079,319 +1050,14 @@ class TcaFlexProcessTest extends UnitTestCase {
 		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
 
 		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => FALSE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-			]
-		];
 
 		// A default value for existing container field aFlexField should have been set
 		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
-		// Also for the other defined language
-		$expected['databaseRow']['aField']['data']['sDEF']['lEN']['section_1']['el']['1']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
 
 		// Dummy row values for container_1 on lDEF sheet
 		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['templateRows']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
-		// Dummy row values for container_1 on lDEF sheet
-		$expected['databaseRow']['aField']['data']['sDEF']['lEN']['section_1']['templateRows']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
-
-		$this->assertEquals($expected, $this->subject->addData($input));
-	}
-
-	/**
-	 * @test
-	 */
-	public function addDataSetsValuesAndStructureForSectionContainerElementsWithLangChildren() {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [
-								'section_1' => [
-									'el' => [
-										'1' => [
-											'container_1' => [
-												// It should set a default for both vDEF and vEN
-												'el' => [
-												],
-											],
-										],
-										'2' => [
-											'container_1' => [
-												'el' => [
-													'aFlexField' => [
-														// It should keep this value
-														'vDEF' => 'dbValue',
-														// It should set a default for vEN
-													],
-												],
-											],
-										],
-									],
-								],
-							],
-						],
-					],
-					'meta' => [],
-				],
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds' => [
-								'meta' => [
-									'langChildren' => 1,
-								],
-								'sheets' => [
-									'sDEF' => [
-										'ROOT' => [
-											'type' => 'array',
-											'el' => [
-												'section_1' => [
-													'section' => '1',
-													'type' => 'array',
-													'el' => [
-														'container_1' => [
-															'type' => 'array',
-															'el' => [
-																'aFlexField' => [
-																	'label' => 'aFlexFieldLabel',
-																	'config' => [
-																		'type' => 'input',
-																		'default' => 'defaultValue',
-																	],
-																],
-															],
-														],
-													],
-												],
-											],
-										],
-									],
-								],
-							],
-						],
-					],
-				],
-			],
-			'pageTsConfigMerged' => [],
-		];
-
-		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
-			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
-		];
-
-		/** @var LanguageService|ObjectProphecy $languageService */
-		$languageService = $this->prophesize(LanguageService::class);
-		$GLOBALS['LANG'] = $languageService->reveal();
-		$languageService->sL(Argument::cetera())->willReturnArgument(0);
-
-		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
-		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
-
-		$expected = $input;
-		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
-			'availableLanguageCodes' => [
-				0 => 'DEF',
-				1 => 'EN',
-			],
-			'langDisable' => FALSE,
-			'langChildren' => TRUE,
-			'languagesOnSheetLevel' => [
-				0 => 'DEF',
-			],
-			'languagesOnElement' => [
-				0 => 'DEF',
-				1 => 'EN',
-			]
-		];
-
-		// A default value for existing container field aFlexField should have been set
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['aFlexField']['vEN'] = 'defaultValue';
-		// Also for the other defined language
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['2']['container_1']['el']['aFlexField']['vEN'] = 'defaultValue';
-
-		// There should be a templateRow for container_1 with defaultValue set for both languages
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['templateRows']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
-		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['templateRows']['container_1']['el']['aFlexField']['vEN'] = 'defaultValue';
 
 		$this->assertEquals($expected, $this->subject->addData($input));
 	}
 
-
-	/**
-	 * Date provider for addDataSetsLanguageFlags
-	 *
-	 * @return array
-	 */
-	public function addDataSetsLanguageFlagsDataProvider() {
-		return [
-			'Default values are set' => [
-				'sheets' => [
-					'sDEF' => [
-						'ROOT' => [],
-					],
-				],
-				FALSE,
-				FALSE,
-				[],
-				[0 => 'DEF'],
-			],
-			'langDisable is set to FALSE' => [
-				'sheets' => [
-					'meta' => [
-						'langDisable' => 0,
-					],
-					'sDEF' => [
-						'ROOT' => [],
-					],
-				],
-				FALSE,
-				FALSE,
-				[],
-				[0 => 'DEF'],
-			],
-			'langDisable is set to TRUE' => [
-				'sheets' => [
-					'meta' => [
-						'langDisable' => 1,
-					],
-					'sDEF' => [
-						'ROOT' => [],
-					],
-				],
-				TRUE,
-				FALSE,
-				[],
-				[0 => 'DEF'],
-			],
-			'langChildren is set to FALSE' => [
-				'sheets' => [
-					'meta' => [
-						'langChildren' => 0,
-					],
-					'sDEF' => [
-						'ROOT' => [],
-					],
-				],
-				FALSE,
-				FALSE,
-				[],
-				[0 => 'DEF'],
-			],
-			'langChildren is set to TRUE' => [
-				'sheets' => [
-					'meta' => [
-						'langChildren' => 1,
-					],
-					'sDEF' => [
-						'ROOT' => [],
-					],
-				],
-				FALSE,
-				TRUE,
-				[0 => 'DEF'],
-				[],
-			],
-			'langDisable and langChildren are set' => [
-				'sheets' => [
-					'meta' => [
-						'langDisable' => 1,
-						'langChildren' => 1,
-					],
-					'sDEF' => [
-						'ROOT' => [],
-					],
-				],
-				TRUE,
-				TRUE,
-				[0 => 'DEF'],
-				[],
-			],
-		];
-	}
-
-	/**
-	 * @test
-	 * @param $flexform
-	 * @param $expectedLangDisable
-	 * @param $expectedLangChildren
-	 * @param $expectedLanguagesOnSheetLevel
-	 * @param $expectedLanguagesOnElement
-	 * @dataProvider addDataSetsLanguageFlagsDataProvider
-	 */
-	public function addDataSetsLanguageFlags($flexform, $expectedLangDisable, $expectedLangChildren, $expectedLanguagesOnSheetLevel, $expectedLanguagesOnElement) {
-		$input = [
-			'tableName' => 'aTable',
-			'databaseRow' => [
-				'aField' => [
-					'data' => [
-						'sDEF' => [
-							'lDEF' => [
-								'input_1' => [
-									'vDEF' => 'input1 text',
-								],
-							],
-						],
-					],
-					'meta' => [],
-				],
-				'pointerField' => 'aFlex',
-			],
-			'systemLanguageRows' => [
-				0 => [
-					'uid' => 0,
-					'iso' => 'DEF',
-				],
-				1 => [
-					'uid' => 1,
-					'iso' => 'EN',
-				],
-			],
-			'processedTca' => [
-				'columns' => [
-					'aField' => [
-						'config' => [
-							'type' => 'flex',
-							'ds_pointerField' => 'pointerField',
-							'ds' => $flexform,
-						],
-					],
-				],
-			],
-		];
-
-		$result = $this->subject->addData($input);
-
-		$this->assertEquals($expectedLangDisable, $result['processedTca']['columns']['aField']['config']['ds']['meta']['langDisable']);
-		$this->assertEquals($expectedLangChildren, $result['processedTca']['columns']['aField']['config']['ds']['meta']['langChildren']);
-		$this->assertEquals($expectedLanguagesOnSheetLevel, $result['processedTca']['columns']['aField']['config']['ds']['meta']['languagesOnSheetLevel']);
-		$this->assertEquals($expectedLanguagesOnElement, $result['processedTca']['columns']['aField']['config']['ds']['meta']['languagesOnElement']);
-	}
-
 }
diff --git a/typo3/sysext/compatibility6/Classes/Configuration/FlexForm/FlexFormTools.php b/typo3/sysext/compatibility6/Classes/Configuration/FlexForm/FlexFormTools.php
new file mode 100644
index 000000000000..70d97bca69e3
--- /dev/null
+++ b/typo3/sysext/compatibility6/Classes/Configuration/FlexForm/FlexFormTools.php
@@ -0,0 +1,412 @@
+<?php
+namespace TYPO3\CMS\Compatibility6\Configuration\FlexForm;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Contains functions for manipulating flex form data
+ */
+class FlexFormTools {
+
+	/**
+	 * If set, the charset of data XML is converted to system charset.
+	 *
+	 * @var bool
+	 */
+	public $convertCharset = FALSE;
+
+	/**
+	 * If set, section indexes are re-numbered before processing
+	 *
+	 * @var bool
+	 */
+	public $reNumberIndexesOfSectionData = FALSE;
+
+	/**
+	 * Contains data structure when traversing flexform
+	 *
+	 * @var array
+	 */
+	public $traverseFlexFormXMLData_DS = array();
+
+	/**
+	 * Contains data array when traversing flexform
+	 *
+	 * @var array
+	 */
+	public $traverseFlexFormXMLData_Data = array();
+
+	/**
+	 * Options for array2xml() for flexform.
+	 * This will map the weird keys from the internal array to tags that could potentially be checked with a DTD/schema
+	 *
+	 * @var array
+	 */
+	public $flexArray2Xml_options = array(
+		'parentTagMap' => array(
+			'data' => 'sheet',
+			'sheet' => 'language',
+			'language' => 'field',
+			'el' => 'field',
+			'field' => 'value',
+			'field:el' => 'el',
+			'el:_IS_NUM' => 'section',
+			'section' => 'itemType'
+		),
+		'disableTypeAttrib' => 2
+	);
+
+	/**
+	 * Reference to object called
+	 *
+	 * @var object
+	 */
+	public $callBackObj = NULL;
+
+	/**
+	 * Used for accumulation of clean XML
+	 *
+	 * @var array
+	 */
+	public $cleanFlexFormXML = array();
+
+	/**
+	 * Handler for Flex Forms
+	 *
+	 * @param string $table The table name of the record
+	 * @param string $field The field name of the flexform field to work on
+	 * @param array $row The record data array
+	 * @param object $callBackObj Object in which the call back function is located
+	 * @param string $callBackMethod_value Method name of call back function in object for values
+	 * @return bool|string If TRUE, error happened (error string returned)
+	 */
+	public function traverseFlexFormXMLData($table, $field, $row, $callBackObj, $callBackMethod_value) {
+		if (!is_array($GLOBALS['TCA'][$table]) || !is_array($GLOBALS['TCA'][$table]['columns'][$field])) {
+			return 'TCA table/field was not defined.';
+		}
+		$this->callBackObj = $callBackObj;
+		// Get Data Structure:
+		$dataStructArray = BackendUtility::getFlexFormDS($GLOBALS['TCA'][$table]['columns'][$field]['config'], $row, $table, $field);
+		// If data structure was ok, proceed:
+		if (is_array($dataStructArray)) {
+			// Get flexform XML data:
+			$xmlData = $row[$field];
+			// Convert charset:
+			if ($this->convertCharset) {
+				$xmlHeaderAttributes = GeneralUtility::xmlGetHeaderAttribs($xmlData);
+				$storeInCharset = strtolower($xmlHeaderAttributes['encoding']);
+				if ($storeInCharset) {
+					$currentCharset = $GLOBALS['LANG']->charSet;
+					$xmlData = $GLOBALS['LANG']->csConvObj->conv($xmlData, $storeInCharset, $currentCharset, 1);
+				}
+			}
+			$editData = GeneralUtility::xml2array($xmlData);
+			if (!is_array($editData)) {
+				return 'Parsing error: ' . $editData;
+			}
+			// Language settings:
+			$langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0;
+			$langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0;
+			// Empty or invalid <meta>
+			if (!is_array($editData['meta'])) {
+				$editData['meta'] = array();
+			}
+			$editData['meta']['currentLangId'] = array();
+			$languages = $this->getAvailableLanguages();
+			foreach ($languages as $lInfo) {
+				$editData['meta']['currentLangId'][] = $lInfo['ISOcode'];
+			}
+			if (empty($editData['meta']['currentLangId'])) {
+				$editData['meta']['currentLangId'] = array('DEF');
+			}
+			$editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']);
+			if ($langChildren || $langDisabled) {
+				$lKeys = array('DEF');
+			} else {
+				$lKeys = $editData['meta']['currentLangId'];
+			}
+			// Tabs sheets
+			if (is_array($dataStructArray['sheets'])) {
+				$sKeys = array_keys($dataStructArray['sheets']);
+			} else {
+				$sKeys = array('sDEF');
+			}
+			// Traverse languages:
+			foreach ($lKeys as $lKey) {
+				foreach ($sKeys as $sheet) {
+					$sheetCfg = $dataStructArray['sheets'][$sheet];
+					list($dataStruct, $sheet) = GeneralUtility::resolveSheetDefInDS($dataStructArray, $sheet);
+					// Render sheet:
+					if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) {
+						// Separate language key
+						$lang = 'l' . $lKey;
+						$PA['vKeys'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : array('DEF');
+						$PA['lKey'] = $lang;
+						$PA['callBackMethod_value'] = $callBackMethod_value;
+						$PA['table'] = $table;
+						$PA['field'] = $field;
+						$PA['uid'] = $row['uid'];
+						$this->traverseFlexFormXMLData_DS = &$dataStruct;
+						$this->traverseFlexFormXMLData_Data = &$editData;
+						// Render flexform:
+						$this->traverseFlexFormXMLData_recurse($dataStruct['ROOT']['el'], $editData['data'][$sheet][$lang], $PA, 'data/' . $sheet . '/' . $lang);
+					} else {
+						return 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".';
+					}
+				}
+			}
+		} else {
+			return 'Data Structure ERROR: ' . $dataStructArray;
+		}
+	}
+
+	/**
+	 * Recursively traversing flexform data according to data structure and element data
+	 *
+	 * @param array $dataStruct (Part of) data structure array that applies to the sub section of the flexform data we are processing
+	 * @param array $editData (Part of) edit data array, reflecting current part of data structure
+	 * @param array $PA Additional parameters passed.
+	 * @param string $path Telling the "path" to the element in the flexform XML
+	 * @return array
+	 */
+	public function traverseFlexFormXMLData_recurse($dataStruct, $editData, &$PA, $path = '') {
+		if (is_array($dataStruct)) {
+			foreach ($dataStruct as $key => $value) {
+				// The value of each entry must be an array.
+				if (is_array($value)) {
+					if ($value['type'] == 'array') {
+						// Array (Section) traversal
+						if ($value['section']) {
+							$cc = 0;
+							if (is_array($editData[$key]['el'])) {
+								if ($this->reNumberIndexesOfSectionData) {
+									$temp = array();
+									$c3 = 0;
+									foreach ($editData[$key]['el'] as $v3) {
+										$temp[++$c3] = $v3;
+									}
+									$editData[$key]['el'] = $temp;
+								}
+								foreach ($editData[$key]['el'] as $k3 => $v3) {
+									if (is_array($v3)) {
+										$cc = $k3;
+										$theType = key($v3);
+										$theDat = $v3[$theType];
+										$newSectionEl = $value['el'][$theType];
+										if (is_array($newSectionEl)) {
+											$this->traverseFlexFormXMLData_recurse(array($theType => $newSectionEl), array($theType => $theDat), $PA, $path . '/' . $key . '/el/' . $cc);
+										}
+									}
+								}
+							}
+						} else {
+							// Array traversal
+							if (is_array($editData) && is_array($editData[$key])) {
+								$this->traverseFlexFormXMLData_recurse($value['el'], $editData[$key]['el'], $PA, $path . '/' . $key . '/el');
+							}
+						}
+					} elseif (is_array($value['TCEforms']['config'])) {
+						// Processing a field value:
+						foreach ($PA['vKeys'] as $vKey) {
+							$vKey = 'v' . $vKey;
+							// Call back
+							if ($PA['callBackMethod_value'] && is_array($editData) && is_array($editData[$key])) {
+								$this->executeCallBackMethod($PA['callBackMethod_value'], array($value, $editData[$key][$vKey], $PA, $path . '/' . $key . '/' . $vKey, $this));
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Execute method on callback object
+	 *
+	 * @param string $methodName Method name to call
+	 * @param array $parameterArray Parameters
+	 * @return mixed Result of callback object
+	 */
+	protected function executeCallBackMethod($methodName, array $parameterArray) {
+		return call_user_func_array(array($this->callBackObj, $methodName), $parameterArray);
+	}
+
+	/**
+	 * Returns an array of available languages to use for FlexForm operations
+	 *
+	 * @return array
+	 */
+	public function getAvailableLanguages() {
+		$isL = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('static_info_tables');
+		// Find all language records in the system
+		$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
+			'language_isocode,static_lang_isocode,title,uid',
+			'sys_language',
+			'pid=0' . BackendUtility::deleteClause('sys_language'),
+			'',
+			'title'
+		);
+		// Traverse them
+		$output = array();
+		$output[0] = array(
+			'uid' => 0,
+			'title' => 'Default language',
+			'ISOcode' => 'DEF'
+		);
+		while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
+			$output[$row['uid']] = $row;
+			if (!empty($row['language_isocode'])) {
+				$output[$row['uid']]['ISOcode'] = $row['language_isocode'];
+			} elseif ($isL && $row['static_lang_isocode']) {
+				\TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog('Usage of the field "static_lang_isocode" is discouraged, and will stop working with CMS 8. Use the built-in language field "language_isocode" in your sys_language records.');
+				$rr = BackendUtility::getRecord('static_languages', $row['static_lang_isocode'], 'lg_iso_2');
+				if ($rr['lg_iso_2']) {
+					$output[$row['uid']]['ISOcode'] = $rr['lg_iso_2'];
+				}
+			}
+			if (!$output[$row['uid']]['ISOcode']) {
+				unset($output[$row['uid']]);
+			}
+		}
+		$GLOBALS['TYPO3_DB']->sql_free_result($res);
+		return $output;
+	}
+
+	/***********************************
+	 *
+	 * Processing functions
+	 *
+	 ***********************************/
+	/**
+	 * Cleaning up FlexForm XML to hold only the values it may according to its Data Structure. Also the order of tags will follow that of the data structure.
+	 * BE CAREFUL: DO not clean records in workspaces unless IN the workspace! The Data Structure might resolve falsely on a workspace record when cleaned from Live workspace.
+	 *
+	 * @param string $table Table name
+	 * @param string $field Field name of the flex form field in which the XML is found that should be cleaned.
+	 * @param array $row The record
+	 * @return string Clean XML from FlexForm field
+	 */
+	public function cleanFlexFormXML($table, $field, $row) {
+		// New structure:
+		$this->cleanFlexFormXML = array();
+		// Create and call iterator object:
+		$flexObj = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools::class);
+		$flexObj->reNumberIndexesOfSectionData = TRUE;
+		$flexObj->traverseFlexFormXMLData($table, $field, $row, $this, 'cleanFlexFormXML_callBackFunction');
+		return $this->flexArray2Xml($this->cleanFlexFormXML, TRUE);
+	}
+
+	/**
+	 * Call back function for \TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools class
+	 * Basically just setting the value in a new array (thus cleaning because only values that are valid are visited!)
+	 *
+	 * @param array $dsArr Data structure for the current value
+	 * @param mixed $data Current value
+	 * @param array $PA Additional configuration used in calling function
+	 * @param string $path Path of value in DS structure
+	 * @param FlexFormTools $pObj caller
+	 * @return void
+	 */
+	public function cleanFlexFormXML_callBackFunction($dsArr, $data, $PA, $path, $pObj) {
+		// Just setting value in our own result array, basically replicating the structure:
+		$pObj->setArrayValueByPath($path, $this->cleanFlexFormXML, $data);
+		// Looking if an "extension" called ".vDEFbase" is found and if so, accept that too:
+		if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase']) {
+			$vDEFbase = $pObj->getArrayValueByPath($path . '.vDEFbase', $pObj->traverseFlexFormXMLData_Data);
+			if (isset($vDEFbase)) {
+				$pObj->setArrayValueByPath($path . '.vDEFbase', $this->cleanFlexFormXML, $vDEFbase);
+			}
+		}
+	}
+
+	/***********************************
+	 *
+	 * Multi purpose functions
+	 *
+	 ***********************************/
+	/**
+	 * Get a value from a multi-dimensional array by giving a path "../../.." pointing to the element
+	 *
+	 * @param string $pathArray The path pointing to the value field, eg. test/2/title to access $array['test'][2]['title']
+	 * @param array $array Array to get value from. Passed by reference so the value returned can be used to change the value in the array!
+	 * @return mixed Value returned
+	 */
+	public function &getArrayValueByPath($pathArray, &$array) {
+		if (!is_array($pathArray)) {
+			$pathArray = explode('/', $pathArray);
+		}
+		if (is_array($array) && !empty($pathArray)) {
+			$key = array_shift($pathArray);
+			if (isset($array[$key])) {
+				if (empty($pathArray)) {
+					return $array[$key];
+				}
+				return $this->getArrayValueByPath($pathArray, $array[$key]);
+			}
+			return NULL;
+		}
+	}
+
+	/**
+	 * Set a value in a multi-dimensional array by giving a path "../../.." pointing to the element
+	 *
+	 * @param string $pathArray The path pointing to the value field, eg. test/2/title to access $array['test'][2]['title']
+	 * @param array $array Array to set value in. Passed by reference so the value returned can be used to change the value in the array!
+	 * @param mixed $value Value to set
+	 * @return mixed Value returned
+	 */
+	public function setArrayValueByPath($pathArray, &$array, $value) {
+		if (isset($value)) {
+			if (!is_array($pathArray)) {
+				$pathArray = explode('/', $pathArray);
+			}
+			if (is_array($array) && !empty($pathArray)) {
+				$key = array_shift($pathArray);
+				if (empty($pathArray)) {
+					$array[$key] = $value;
+					return TRUE;
+				}
+				if (!isset($array[$key])) {
+					$array[$key] = array();
+				}
+				return $this->setArrayValueByPath($pathArray, $array[$key], $value);
+
+			}
+		}
+	}
+
+	/**
+	 * Convert FlexForm data array to XML
+	 *
+	 * @param array $array Array to output in <T3FlexForms> XML
+	 * @param bool $addPrologue If set, the XML prologue is returned as well.
+	 * @return string XML content.
+	 */
+	public function flexArray2Xml($array, $addPrologue = FALSE) {
+		if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexformForceCDATA']) {
+			$this->flexArray2Xml_options['useCDATA'] = 1;
+		}
+		$options = $GLOBALS['TYPO3_CONF_VARS']['BE']['niceFlexFormXMLtags'] ? $this->flexArray2Xml_options : array();
+		$spaceInd = $GLOBALS['TYPO3_CONF_VARS']['BE']['compactFlexFormXML'] ? -1 : 4;
+		$output = GeneralUtility::array2xml($array, '', 0, 'T3FlexForms', $spaceInd, $options);
+		if ($addPrologue) {
+			$output = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>' . LF . $output;
+		}
+		return $output;
+	}
+
+}
diff --git a/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormElementContainer.php b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormElementContainer.php
new file mode 100644
index 000000000000..95838be88b46
--- /dev/null
+++ b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormElementContainer.php
@@ -0,0 +1,224 @@
+<?php
+namespace TYPO3\CMS\Compatibility6\Form\Container;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+
+/**
+ * The container handles single elements.
+ *
+ * This one is called by FlexFormTabsContainer, FlexFormNoTabsContainer or FlexFormContainerContainer.
+ * For single fields, the code is similar to SingleFieldContainer, processing will end up in single
+ * element classes depending on specific type of an element. Additionally, it determines if a
+ * section is handled and hands over to FlexFormSectionContainer in this case.
+ */
+class FlexFormElementContainer extends AbstractContainer {
+
+	/**
+	 * Entry method
+	 *
+	 * @return array As defined in initializeResultArray() of AbstractNode
+	 */
+	public function render() {
+		$table = $this->data['tableName'];
+		$row = $this->data['databaseRow'];
+		$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
+		$flexFormRowData = $this->data['flexFormRowData'];
+		$flexFormFormPrefix = $this->data['flexFormFormPrefix'];
+		$parameterArray = $this->data['parameterArray'];
+		$metaData = $this->data['parameterArray']['fieldConf']['config']['ds']['meta'];
+
+		$languageService = $this->getLanguageService();
+		/** @var IconFactory $iconFactory */
+		$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+		$resultArray = $this->initializeResultArray();
+		foreach ($flexFormDataStructureArray as $flexFormFieldName => $flexFormFieldArray) {
+			if (
+				// No item array found at all
+				!is_array($flexFormFieldArray)
+				// Not a section or container and not a list of single items
+				|| (!isset($flexFormFieldArray['type']) && !is_array($flexFormFieldArray['config']))
+			) {
+				continue;
+			}
+
+			if ($flexFormFieldArray['type'] === 'array') {
+				// Section
+				if (empty($flexFormFieldArray['section'])) {
+					$resultArray['html'] = LF . 'Section expected at ' . $flexFormFieldName . ' but not found';
+					continue;
+				}
+
+				$sectionTitle = '';
+				if (!empty($flexFormFieldArray['title'])) {
+					$sectionTitle = $languageService->sL($flexFormFieldArray['title']);
+				}
+
+				$options = $this->data;
+				$options['flexFormDataStructureArray'] = $flexFormFieldArray['el'];
+				$options['flexFormRowData'] = is_array($flexFormRowData[$flexFormFieldName]['el']) ? $flexFormRowData[$flexFormFieldName]['el'] : array();
+				$options['flexFormSectionType'] = $flexFormFieldName;
+				$options['flexFormSectionTitle'] = $sectionTitle;
+				$options['renderType'] = 'flexFormSectionContainer';
+				$sectionContainerResult = $this->nodeFactory->create($options)->render();
+				$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $sectionContainerResult);
+			} else {
+				if (is_array($metaData) && isset($metaData['langChildren']) && isset($metaData['languagesOnElement'])) {
+					$lkeys = $metaData['languagesOnElement'];
+					array_walk($lkeys, function (&$value) {
+						$value = 'v' . $value;
+					});
+				} else {
+					$lkeys = array('vDEF');
+				}
+				$html = array();
+				foreach ($lkeys as $lkey) {
+					// Set up options for single element
+					$fakeParameterArray = array(
+						'fieldConf' => array(
+							'label' => $languageService->sL(trim($flexFormFieldArray['label'])),
+							'config' => $flexFormFieldArray['config'],
+							'defaultExtras' => $flexFormFieldArray['defaultExtras'],
+							'onChange' => $flexFormFieldArray['onChange'],
+						),
+					);
+
+					$alertMsgOnChange = '';
+					if (
+						$fakeParameterArray['fieldConf']['onChange'] === 'reload'
+						|| !empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $GLOBALS['TCA'][$table]['ctrl']['type'] === $flexFormFieldName
+						|| !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList($GLOBALS['TCA'][$table]['ctrl']['requestUpdate'], $flexFormFieldName)
+					) {
+						if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
+							$alertMsgOnChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });';
+						} else {
+							$alertMsgOnChange = 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm();}';
+						}
+					}
+					$fakeParameterArray['fieldChangeFunc'] = $parameterArray['fieldChangeFunc'];
+					if ($alertMsgOnChange) {
+						$fakeParameterArray['fieldChangeFunc']['alert'] = $alertMsgOnChange;
+					}
+
+					$fakeParameterArray['onFocus'] = $parameterArray['onFocus'];
+					$fakeParameterArray['label'] = $parameterArray['label'];
+					$fakeParameterArray['itemFormElName'] = $parameterArray['itemFormElName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']';
+					$fakeParameterArray['itemFormElID'] = $fakeParameterArray['itemFormElName'];
+					if (isset($flexFormRowData[$flexFormFieldName][$lkey])) {
+						$fakeParameterArray['itemFormElValue'] = $flexFormRowData[$flexFormFieldName][$lkey];
+					} else {
+						$fakeParameterArray['itemFormElValue'] = $fakeParameterArray['fieldConf']['config']['default'];
+					}
+
+					$options = $this->data;
+					$options['parameterArray'] = $fakeParameterArray;
+					$options['elementBaseName'] = $this->data['elementBaseName'] . $flexFormFormPrefix . '[' . $flexFormFieldName . '][' . $lkey . ']';
+
+					if (!empty($flexFormFieldArray['config']['renderType'])) {
+						$options['renderType'] = $flexFormFieldArray['config']['renderType'];
+					} else {
+						// Fallback to type if no renderType is given
+						$options['renderType'] = $flexFormFieldArray['config']['type'];
+					}
+					$childResult = $this->nodeFactory->create($options)->render();
+
+					$theTitle = htmlspecialchars($fakeParameterArray['fieldConf']['label']);
+					$defInfo = array();
+
+					// Possible line breaks in the label through xml: \n => <br/>, usage of nl2br() not possible, so it's done through str_replace (?!)
+					$processedTitle = str_replace('\\n', '<br />', $theTitle);
+					// @todo: Similar to the processing within SingleElementContainer ... use it from there?!
+					$html[] = '<div class="form-group t3js-formengine-palette-field t3js-formengine-validation-marker">';
+					$html[] = '<label class="t3js-formengine-label">';
+					if (is_array($metaData) && isset($metaData['langChildren']) && $metaData['langChildren']) {
+						// Find language uid of this iso code
+						$languageUid = 0;
+						$lKeyWithoutV = substr($lkey, 1);
+						if ($lKeyWithoutV !== 'DEF') {
+							foreach ($this->data['systemLanguageRows'] as $systemLanguageRow) {
+								if ($systemLanguageRow['iso'] === $lKeyWithoutV) {
+									$languageUid = $systemLanguageRow['uid'];
+									break;
+								}
+							}
+						}
+						$languageIcon = $iconFactory->getIcon($this->data['systemLanguageRows'][$languageUid]['flagIconIdentifier'], Icon::SIZE_SMALL)->render();
+						$html[] = $languageIcon;
+					}
+					$html[] = BackendUtility::wrapInHelp($parameterArray['_cshKey'], $flexFormFieldName, $processedTitle);
+					$html[] = '</label>';
+					$html[] = '<div class="t3js-formengine-field-item">';
+					$html[] = $childResult['html'];
+					$html[] = implode(LF, $defInfo);
+					$html[] = $this->renderVDEFDiff($flexFormRowData[$flexFormFieldName], $lkey);
+					$html[] = '</div>';
+					$html[] = '</div>';
+				}
+
+				if (!empty($html)) {
+					$resultArray['html'] .= '<div class="form-section">' . implode(LF, $html) . '</div>';
+				}
+				$childResult['html'] = '';
+				$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childResult);
+			}
+		}
+
+		return $resultArray;
+	}
+
+	/**
+	 * Renders the diff-view of vDEF fields in flex forms
+	 *
+	 * @param array $vArray Record array of the record being edited
+	 * @param string $vDEFkey HTML of the form field. This is what we add the content to.
+	 * @return string Item string returned again, possibly with the original value added to.
+	 */
+	protected function renderVDEFDiff($vArray, $vDEFkey) {
+		$item = NULL;
+		if (
+			$GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && isset($vArray[$vDEFkey . '.vDEFbase'])
+			&& (string)$vArray[$vDEFkey . '.vDEFbase'] !== (string)$vArray['vDEF'][0]
+		) {
+			// Create diff-result:
+			$diffUtility = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Utility\DiffUtility::class);
+			$diffres = $diffUtility->makeDiffDisplay($vArray[$vDEFkey . '.vDEFbase'], $vArray['vDEF']);
+			$item = '<div class="typo3-TCEforms-diffBox">' . '<div class="typo3-TCEforms-diffBox-header">'
+				. htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.changeInOrig')) . ':</div>' . $diffres . '</div>';
+		}
+		return $item;
+	}
+
+	/**
+	 * @return LanguageService
+	 */
+	protected function getLanguageService() {
+		return $GLOBALS['LANG'];
+	}
+
+	/**
+	 * @return BackendUserAuthentication
+	 */
+	protected function getBackendUserAuthentication() {
+		return $GLOBALS['BE_USER'];
+	}
+
+}
diff --git a/typo3/sysext/backend/Classes/Form/Container/FlexFormLanguageContainer.php b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormEntryContainer.php
similarity index 88%
rename from typo3/sysext/backend/Classes/Form/Container/FlexFormLanguageContainer.php
rename to typo3/sysext/compatibility6/Classes/Form/Container/FlexFormEntryContainer.php
index 116002280607..b7e1d8e44921 100644
--- a/typo3/sysext/backend/Classes/Form/Container/FlexFormLanguageContainer.php
+++ b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormEntryContainer.php
@@ -1,5 +1,5 @@
 <?php
-namespace TYPO3\CMS\Backend\Form\Container;
+namespace TYPO3\CMS\Compatibility6\Form\Container;
 
 /*
  * This file is part of the TYPO3 CMS project.
@@ -14,20 +14,20 @@ namespace TYPO3\CMS\Backend\Form\Container;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
- * Handle flex form language overlays.
- *
  * Entry container to a flex form element. This container is created by
- * SingleFieldContainer if a type='flexform' field is rendered.
+ * SingleFieldContainer if a type='flex' field is rendered.
+ *
+ * It either forks a FlexFormTabsContainer or a FlexFormNoTabsContainer.
  *
- * For each existing language overlay it forks a FlexFormTabsContainer or a
- * FlexFormNoTabsContainer for rendering a full flex form record of the specific language.
+ * This container additionally handles flex form languages on sheet level.
  */
-class FlexFormLanguageContainer extends AbstractContainer {
+class FlexFormEntryContainer extends AbstractContainer {
 
 	/**
 	 * Entry method
diff --git a/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormNoTabsContainer.php b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormNoTabsContainer.php
new file mode 100644
index 000000000000..eacf04c727ce
--- /dev/null
+++ b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormNoTabsContainer.php
@@ -0,0 +1,77 @@
+<?php
+namespace TYPO3\CMS\Compatibility6\Form\Container;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Handle a flex form that has no tabs.
+ *
+ * This container is called by FlexFormEntryContainer if only a default sheet
+ * exists. It evaluates the display condition and hands over rendering of single
+ * fields to FlexFormElementContainer.
+ */
+class FlexFormNoTabsContainer extends AbstractContainer {
+
+	/**
+	 * Entry method
+	 *
+	 * @return array As defined in initializeResultArray() of AbstractNode
+	 */
+	public function render() {
+		$table = $this->data['tableName'];
+		$row = $this->data['databaseRow'];
+		$fieldName = $this->data['fieldName']; // field name of the flex form field in DB
+		$parameterArray = $this->data['parameterArray'];
+		$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
+		$flexFormCurrentLanguage = $this->data['flexFormCurrentLanguage'];
+		$flexFormRowData = $this->data['flexFormRowData'];
+		$resultArray = $this->initializeResultArray();
+
+		// Flex ds was normalized in flex provider to always have a sheet.
+		// Determine this single sheet name, most often it ends up with sDEF, except if only one sheet was defined
+		$sheetName = array_pop(array_keys($flexFormDataStructureArray['sheets']));
+		$flexFormRowDataSubPart = $flexFormRowData['data'][$sheetName][$flexFormCurrentLanguage];
+
+		// That was taken from GeneralUtility::resolveSheetDefInDS - no idea if it is important
+		unset($flexFormDataStructureArray['meta']);
+
+		if (!is_array($flexFormDataStructureArray['sheets'][$sheetName]['ROOT']['el'])) {
+			$resultArray['html'] = 'Data Structure ERROR: No [\'ROOT\'][\'el\'] element found in flex form definition.';
+			return $resultArray;
+		}
+
+		// Assemble key for loading the correct CSH file
+		// @todo: what is that good for? That is for the title of single elements ... see FlexFormElementContainer!
+		$dsPointerFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['ds_pointerField'], TRUE);
+		$parameterArray['_cshKey'] = $table . '.' . $fieldName;
+		foreach ($dsPointerFields as $key) {
+			if ((string)$row[$key] !== '') {
+				$parameterArray['_cshKey'] .= '.' . $row[$key];
+			}
+		}
+
+		$options = $this->data;
+		$options['flexFormDataStructureArray'] = $flexFormDataStructureArray['sheets'][$sheetName]['ROOT']['el'];
+		$options['flexFormRowData'] = $flexFormRowDataSubPart;
+		$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][' . $flexFormCurrentLanguage . ']';
+		$options['parameterArray'] = $parameterArray;
+
+		$options['renderType'] = 'flexFormElementContainer';
+		return $this->nodeFactory->create($options)->render();
+	}
+
+}
diff --git a/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormTabsContainer.php b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormTabsContainer.php
new file mode 100644
index 000000000000..e58cfe873e79
--- /dev/null
+++ b/typo3/sysext/compatibility6/Classes/Form/Container/FlexFormTabsContainer.php
@@ -0,0 +1,122 @@
+<?php
+namespace TYPO3\CMS\Compatibility6\Form\Container;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Backend\Form\Container\AbstractContainer;
+use TYPO3\CMS\Backend\Template\DocumentTemplate;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Lang\LanguageService;
+
+/**
+ * Handle flex forms that have tabs (multiple "sheets").
+ *
+ * This container is called by FlexFormEntryContainer. It resolves each
+ * sheet and hands rendering of single sheet content over to FlexFormElementContainer.
+ */
+class FlexFormTabsContainer extends AbstractContainer {
+
+	/**
+	 * Entry method
+	 *
+	 * @return array As defined in initializeResultArray() of AbstractNode
+	 */
+	public function render() {
+		$languageService = $this->getLanguageService();
+		$docTemplate = $this->getDocumentTemplate();
+
+		$table = $this->data['tableName'];
+		$row = $this->data['databaseRow'];
+		$fieldName = $this->data['fieldName']; // field name of the flex form field in DB
+		$parameterArray = $this->data['parameterArray'];
+		$flexFormDataStructureArray = $this->data['flexFormDataStructureArray'];
+		$flexFormCurrentLanguage = $this->data['flexFormCurrentLanguage'];
+		$flexFormRowData = $this->data['flexFormRowData'];
+
+		$tabId = 'TCEFORMS:flexform:' . $this->data['parameterArray']['itemFormElName'] . $flexFormCurrentLanguage;
+		$tabIdString = $docTemplate->getDynTabMenuId($tabId);
+		$tabCounter = 0;
+
+		$resultArray = $this->initializeResultArray();
+		$tabsContent = array();
+		foreach ($flexFormDataStructureArray['sheets'] as $sheetName => $sheetDataStructure) {
+			$flexFormRowSheetDataSubPart = $flexFormRowData['data'][$sheetName][$flexFormCurrentLanguage];
+
+			if (!is_array($sheetDataStructure['ROOT']['el'])) {
+				$resultArray['html'] .= LF . 'No Data Structure ERROR: No [\'ROOT\'][\'el\'] found for sheet "' . $sheetName . '".';
+				continue;
+			}
+
+			$tabCounter ++;
+
+			// Assemble key for loading the correct CSH file
+			// @todo: what is that good for? That is for the title of single elements ... see FlexFormElementContainer!
+			$dsPointerFields = GeneralUtility::trimExplode(',', $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['ds_pointerField'], TRUE);
+			$parameterArray['_cshKey'] = $table . '.' . $fieldName;
+			foreach ($dsPointerFields as $key) {
+				if ((string)$row[$key] !== '') {
+					$parameterArray['_cshKey'] .= '.' . $row[$key];
+				}
+			}
+
+			$options = $this->data;
+			$options['flexFormDataStructureArray'] = $sheetDataStructure['ROOT']['el'];
+			$options['flexFormRowData'] = $flexFormRowSheetDataSubPart;
+			$options['flexFormFormPrefix'] = '[data][' . $sheetName . '][' . $flexFormCurrentLanguage . ']';
+			$options['parameterArray'] = $parameterArray;
+			// Merge elements of this tab into a single list again and hand over to
+			// palette and single field container to render this group
+			$options['tabAndInlineStack'][] = array(
+				'tab',
+				$tabIdString . '-' . $tabCounter,
+			);
+			$options['renderType'] = 'flexFormElementContainer';
+			$childReturn = $this->nodeFactory->create($options)->render();
+
+			$tabsContent[] = array(
+				'label' => !empty($sheetDataStructure['ROOT']['sheetTitle']) ? $languageService->sL($sheetDataStructure['ROOT']['sheetTitle']) : $sheetName,
+				'content' => $childReturn['html'],
+				'description' => $sheetDataStructure['ROOT']['sheetDescription'] ? $languageService->sL($sheetDataStructure['ROOT']['sheetDescription']) : '',
+				'linkTitle' => $sheetDataStructure['ROOT']['sheetShortDescr'] ? $languageService->sL($sheetDataStructure['ROOT']['sheetShortDescr']) : '',
+			);
+
+			$childReturn['html'] = '';
+			$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $childReturn);
+		}
+
+		// Feed everything to document template for tab rendering
+		$resultArray['html'] = $docTemplate->getDynamicTabMenu($tabsContent, $tabId, 1, FALSE, FALSE);
+		return $resultArray;
+	}
+
+	/**
+	 * @throws \RuntimeException
+	 * @return DocumentTemplate
+	 */
+	protected function getDocumentTemplate() {
+		$docTemplate = $GLOBALS['TBE_TEMPLATE'];
+		if (!is_object($docTemplate)) {
+			throw new \RuntimeException('No instance of DocumentTemplate found', 1427143328);
+		}
+		return $docTemplate;
+	}
+
+	/**
+	 * @return LanguageService
+	 */
+	protected function getLanguageService() {
+		return $GLOBALS['LANG'];
+	}
+
+}
diff --git a/typo3/sysext/compatibility6/Classes/Form/FormDataProvider/TcaFlexProcess.php b/typo3/sysext/compatibility6/Classes/Form/FormDataProvider/TcaFlexProcess.php
new file mode 100644
index 000000000000..12de40248603
--- /dev/null
+++ b/typo3/sysext/compatibility6/Classes/Form/FormDataProvider/TcaFlexProcess.php
@@ -0,0 +1,715 @@
+<?php
+namespace TYPO3\CMS\Compatibility6\Form\FormDataProvider;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Backend\Form\FormDataCompiler;
+use TYPO3\CMS\Backend\Form\FormDataGroup\FlexFormSegment;
+use TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider;
+use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Process data structures and data values, calculate defaults.
+ *
+ * This is typically the last provider, executed after TcaFlexPrepare
+ */
+class TcaFlexProcess extends AbstractItemProvider implements FormDataProviderInterface {
+
+	/**
+	 * Determine possible pageTsConfig overrides and apply them to ds.
+	 * Determine available languages and sanitize dv for further processing. Then kick
+	 * and validate further details like excluded fields. Finally for each possible
+	 * value and ds call FormDataCompiler with set FlexFormSegment group to resolve
+	 * single field stuff like item processor functions.
+	 *
+	 * @param array $result
+	 * @return array
+	 */
+	public function addData(array $result) {
+		foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
+			if (empty($fieldConfig['config']['type']) || $fieldConfig['config']['type'] !== 'flex') {
+				continue;
+			}
+
+			$flexIdentifier = $this->getFlexIdentifier($result, $fieldName);
+			$pageTsConfigOfFlex = $this->getPageTsOfFlex($result, $fieldName, $flexIdentifier);
+			$result = $this->modifyOuterDataStructure($result, $fieldName, $pageTsConfigOfFlex);
+			$result = $this->removeExcludeFieldsFromDataStructure($result, $fieldName, $flexIdentifier);
+			$result = $this->removeDisabledFieldsFromDataStructure($result, $fieldName, $pageTsConfigOfFlex);
+			$result = $this->prepareLanguageHandlingInDataValues($result, $fieldName);
+			$result = $this->modifyDataStructureAndDataValuesByFlexFormSegmentGroup($result, $fieldName, $pageTsConfigOfFlex);
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Take care of ds_pointerField and friends to determine the correct sub array within
+	 * TCA config ds.
+	 *
+	 * Gets extension identifier. Use second pointer field if it's value is not empty, "list" or "*",
+	 * else it must be a plugin and first one will be used.
+	 * This code basically determines the sub key of ds field:
+	 * config = array(
+	 *  ds => array(
+	 *    'aFlexConfig' => '<flexXml ...
+	 *     ^^^^^^^^^^^
+	 * $flexformIdentifier contains "aFlexConfig" after this operation.
+	 *
+	 * @todo: This method is only implemented half. It basically should do all the
+	 * @todo: pointer handling that is done within BackendUtility::getFlexFormDS() to $srcPointer.
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @return string Pointer
+	 */
+	protected function getFlexIdentifier(array $result, $fieldName) {
+		// @todo: Current implementation with the "list_type, CType" fallback is rather limited and customized for
+		// @todo: tt_content, also it forces a ds_pointerField to be defined and a casual "default" sub array does not work
+		$pointerFields = !empty($result['processedTca']['columns'][$fieldName]['config']['ds_pointerField'])
+			? $result['processedTca']['columns'][$fieldName]['config']['ds_pointerField']
+			: 'list_type,CType';
+		$pointerFields = GeneralUtility::trimExplode(',', $pointerFields);
+		$flexformIdentifier = !empty($result['databaseRow'][$pointerFields[0]]) ? $result['databaseRow'][$pointerFields[0]] : '';
+		if (!empty($result['databaseRow'][$pointerFields[1]])
+			&& $result['databaseRow'][$pointerFields[1]] !== 'list'
+			&& $result['databaseRow'][$pointerFields[1]] !== '*'
+		) {
+			$flexformIdentifier = $result['databaseRow'][$pointerFields[1]];
+		}
+		if (empty($flexformIdentifier)) {
+			$flexformIdentifier = 'default';
+		}
+
+		return $flexformIdentifier;
+	}
+
+	/**
+	 * Determine TCEFORM.aTable.aField.matchingIdentifier
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Handled field name
+	 * @param string $flexIdentifier Determined identifier
+	 * @return array PageTsConfig for this flex
+	 */
+	protected function getPageTsOfFlex(array $result, $fieldName, $flexIdentifier) {
+		$table = $result['tableName'];
+		$pageTs = [];
+		if (!empty($result['pageTsConfigMerged']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])
+			&& is_array($result['pageTsConfigMerged']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'])) {
+			$pageTs = $result['pageTsConfigMerged']['TCEFORM.'][$table . '.'][$fieldName . '.'][$flexIdentifier . '.'];
+		}
+		return $pageTs;
+	}
+
+	/**
+	 * Handle "outer" flex data structure changes like language and sheet
+	 * description. Does not change "TCA" or values of single elements
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @param array $pageTsConfig Given pageTsConfig of this flex form
+	 * @return array Modified item array
+	 */
+	protected function modifyOuterDataStructure(array $result, $fieldName, $pageTsConfig) {
+		$modifiedDataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
+
+		if (isset($pageTsConfig['langDisable'])) {
+			$modifiedDataStructure['meta']['langDisable'] = $pageTsConfig['langDisable'];
+		}
+		if (isset($pageTsConfig['langChildren'])) {
+			$modifiedDataStructure['meta']['langChildren'] = $pageTsConfig['langChildren'];
+		}
+
+		if (isset($modifiedDataStructure['sheets']) && is_array($modifiedDataStructure['sheets'])) {
+			// Handling multiple sheets
+			foreach ($modifiedDataStructure['sheets'] as $sheetName => $sheetStructure) {
+				if (isset($pageTsConfig[$sheetName . '.']) && is_array($pageTsConfig[$sheetName . '.'])) {
+					$pageTsOfSheet = $pageTsConfig[$sheetName . '.'];
+
+					// Remove whole sheet if disabled
+					if (!empty($pageTsOfSheet['disabled'])) {
+						unset($modifiedDataStructure['sheets'][$sheetName]);
+						continue;
+					}
+
+					// sheetTitle, sheetDescription, sheetShortDescr
+					$modifiedDataStructure['sheets'][$sheetName] = $this->modifySingleSheetInformation($sheetStructure, $pageTsOfSheet);
+				}
+			}
+		}
+
+		$modifiedDataStructure['meta']['langDisable'] = isset($modifiedDataStructure['meta']['langDisable'])
+			? (bool)$modifiedDataStructure['meta']['langDisable']
+			: FALSE;
+		$modifiedDataStructure['meta']['langChildren'] = isset($modifiedDataStructure['meta']['langChildren'])
+			? (bool)$modifiedDataStructure['meta']['langChildren']
+			: FALSE;
+
+		$result['processedTca']['columns'][$fieldName]['config']['ds'] = $modifiedDataStructure;
+
+		return $result;
+	}
+
+	/**
+	 * Removes fields from data structure the user has no access to
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @param string $flexIdentifier Determined identifier
+	 * @return array Modified result
+	 */
+	protected function removeExcludeFieldsFromDataStructure(array $result, $fieldName, $flexIdentifier) {
+		$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
+		$backendUser = $this->getBackendUser();
+		if ($backendUser->isAdmin() || !isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
+			return $result;
+		}
+
+		$userNonExcludeFields = GeneralUtility::trimExplode(',', $backendUser->groupData['non_exclude_fields']);
+		$excludeFieldsPrefix = $result['tableName'] . ':' . $fieldName . ';' . $flexIdentifier . ';';
+		$nonExcludeFields = [];
+		foreach ($userNonExcludeFields as $userNonExcludeField) {
+			if (strpos($userNonExcludeField, $excludeFieldsPrefix) !== FALSE) {
+				$exploded = explode(';', $userNonExcludeField);
+				$sheetName = $exploded[2];
+				$fieldName = $exploded[3];
+				$nonExcludeFields[$sheetName] = $fieldName;
+			}
+		}
+
+		foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
+			if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])) {
+				continue;
+			}
+			foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
+				if (!empty($fieldDefinition['exclude']) && empty($nonExcludeFields[$sheetName])) {
+					unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
+				}
+			}
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Handle "outer" flex data structure changes like language and sheet
+	 * description. Does not change "TCA" or values of single elements
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @param array $pageTsConfig Given pageTsConfig of this flex form
+	 * @return array Modified item array
+	 */
+	protected function removeDisabledFieldsFromDataStructure(array $result, $fieldName, $pageTsConfig) {
+		$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
+		if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
+			return $result;
+		}
+		foreach ($dataStructure['sheets'] as $sheetName => $sheetDefinition) {
+			if (!isset($sheetDefinition['ROOT']['el']) || !is_array($sheetDefinition['ROOT']['el'])
+				|| !isset($pageTsConfig[$sheetName . '.'])) {
+				continue;
+			}
+			foreach ($sheetDefinition['ROOT']['el'] as $flexFieldName => $fieldDefinition) {
+				if (!empty($pageTsConfig[$sheetName . '.'][$flexFieldName . '.']['disabled'])) {
+					unset($result['processedTca']['columns'][$fieldName]['config']['ds']['sheets'][$sheetName]['ROOT']['el'][$flexFieldName]);
+				}
+			}
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Remove data values in languages the user has no access to and add dummy entries
+	 * for languages that are available but do not exist in data values yet.
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @return array Modified item array
+	 */
+	protected function prepareLanguageHandlingInDataValues(array $result, $fieldName) {
+		$backendUser = $this->getBackendUser();
+		$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
+
+		$langDisabled = $dataStructure['meta']['langDisable'];
+		$langChildren = $dataStructure['meta']['langChildren'];
+
+		// Existing page language overlays are only considered if options.checkPageLanguageOverlay is set in userTs
+		$checkPageLanguageOverlay = FALSE;
+		if (isset($result['userTsConfig']['options.']) && is_array($result['userTsConfig']['options.'])
+			&& array_key_exists('checkPageLanguageOverlay', $result['userTsConfig']['options.'])
+		) {
+			$checkPageLanguageOverlay = (bool)$result['userTsConfig']['options.']['checkPageLanguageOverlay'];
+		}
+
+		$systemLanguageRows = $result['systemLanguageRows'];
+
+		// Contains all language iso code that are valid and user has access to
+		$availableLanguageCodes = [];
+		$defaultCodeWasAdded = FALSE;
+		foreach ($systemLanguageRows as $systemLanguageRow) {
+			$isoCode = $systemLanguageRow['iso'];
+			$isAvailable = TRUE;
+			if ($langDisabled && $isoCode !== 'DEF') {
+				$isAvailable = FALSE;
+			}
+			// @todo: Is it possible a user has no write access to default lang? If so, what to do?
+			if (!$backendUser->checkLanguageAccess($systemLanguageRow['uid'])) {
+				$isAvailable = FALSE;
+			}
+			if ($checkPageLanguageOverlay && $systemLanguageRow['uid'] > 0) {
+				$found = FALSE;
+				foreach ($result['pageLanguageOverlayRows'] as $overlayRow) {
+					if ((int)$overlayRow['sys_language_uid'] === (int)$systemLanguageRow['uid']) {
+						$found = TRUE;
+						break;
+					}
+				}
+				if (!$found) {
+					$isAvailable = FALSE;
+				}
+			}
+			if ($isoCode === 'DEF' && $defaultCodeWasAdded) {
+				$isAvailable = FALSE;
+			}
+			if ($isAvailable) {
+				$availableLanguageCodes[] = $isoCode;
+			}
+			if ($isoCode === 'DEF') {
+				$defaultCodeWasAdded = TRUE;
+			}
+		}
+		// Set the list of available languages in the data structure "meta" section to have it
+		// available for the render engine to iterate over it.
+		$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['availableLanguageCodes'] = $availableLanguageCodes;
+
+		if (!$langChildren) {
+			$allowedLanguageSheetKeys = [];
+			foreach ($availableLanguageCodes as $isoCode) {
+				$allowedLanguageSheetKeys['l' . $isoCode] = [];
+			}
+			$result = $this->setLanguageSheetsInDataValues($result, $fieldName, $allowedLanguageSheetKeys);
+
+			// With $langChildren = 0, values must only contain vDEF prefixed keys
+			$allowedValueLevelLanguageKeys = [];
+			$allowedValueLevelLanguageKeys['vDEF'] = [];
+			$allowedValueLevelLanguageKeys['vDEF.vDEFbase'] = [];
+			// A richtext special
+			$allowedValueLevelLanguageKeys['_TRANSFORM_vDEF.vDEFbase'] = [];
+			$result = $this->setLanguageValueLevelValues($result, $fieldName, $allowedValueLevelLanguageKeys);
+		} else {
+			// langChildren is set - only lDEF as sheet language is allowed, but more fields on value field level
+			$allowedLanguageSheetKeys = [
+				'lDEF' => [],
+			];
+			$result = $this->setLanguageSheetsInDataValues($result, $fieldName, $allowedLanguageSheetKeys);
+
+			$allowedValueLevelLanguageKeys = [];
+			foreach ($availableLanguageCodes as $isoCode) {
+				$allowedValueLevelLanguageKeys['v' . $isoCode] = [];
+				$allowedValueLevelLanguageKeys['v' . $isoCode . '.vDEFbase'] = [];
+				$allowedValueLevelLanguageKeys['_TRANSFORM_v' . $isoCode . '.vDEFbase'] = [];
+			}
+			$result = $this->setLanguageValueLevelValues($result, $fieldName, $allowedValueLevelLanguageKeys);
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Feed single flex field and data to FlexFormSegment FormData compiler and merge result.
+	 * This one is nasty. Goal is to have processed TCA stuff in DS and also have validated / processed data values.
+	 *
+	 * Three main parts in this method:
+	 * * Process values of existing section container for default values
+	 * * Process values and TCA of possible section container and create a default value row for each
+	 * * Process TCA of "normal" fields and have default values in data ['templateRows']['containerName'] parallel to section ['el']
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @param array $pageTsConfig Given pageTsConfig of this flex form
+	 * @return array Modified item array
+	 */
+	protected function modifyDataStructureAndDataValuesByFlexFormSegmentGroup(array $result, $fieldName, $pageTsConfig) {
+		$dataStructure = $result['processedTca']['columns'][$fieldName]['config']['ds'];
+		$dataValues = $result['databaseRow'][$fieldName];
+		$tableName = $result['tableName'];
+
+		$availableLanguageCodes = $result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['availableLanguageCodes'];
+		if ($dataStructure['meta']['langChildren']) {
+			$languagesOnSheetLevel = [ 'DEF' ];
+			$languagesOnElementLevel = $availableLanguageCodes;
+		} else {
+			$languagesOnSheetLevel = $availableLanguageCodes;
+			$languagesOnElementLevel = [ 'DEF' ];
+		}
+
+		$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['languagesOnSheetLevel'] = $languagesOnSheetLevel;
+		$result['processedTca']['columns'][$fieldName]['config']['ds']['meta']['languagesOnElement'] = $languagesOnElementLevel;
+
+		if (!isset($dataStructure['sheets']) || !is_array($dataStructure['sheets'])) {
+			return $result;
+		}
+
+		/** @var FlexFormSegment $formDataGroup */
+		$formDataGroup = GeneralUtility::makeInstance(FlexFormSegment::class);
+		/** @var FormDataCompiler $formDataCompiler */
+		$formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
+
+		foreach ($dataStructure['sheets'] as $dataStructureSheetName => $dataStructureSheetDefinition) {
+			if (!isset($dataStructureSheetDefinition['ROOT']['el']) || !is_array($dataStructureSheetDefinition['ROOT']['el'])) {
+				continue;
+			}
+			$dataStructureSheetElements = $dataStructureSheetDefinition['ROOT']['el'];
+
+			// Prepare pageTsConfig of this sheet
+			$pageTsConfigMerged['TCEFORM.'][$tableName . '.'] = [];
+			if (isset($pageTsConfig[$dataStructureSheetName . '.']) && is_array($pageTsConfig[$dataStructureSheetName . '.'])) {
+				$pageTsConfigMerged['TCEFORM.'][$tableName . '.'] = $pageTsConfig[$dataStructureSheetName . '.'];
+			}
+
+			foreach ($languagesOnSheetLevel as $isoSheetLevel) {
+				$langSheetLevel = 'l' . $isoSheetLevel;
+				foreach ($dataStructureSheetElements as $dataStructureSheetElementName => $dataStructureSheetElementDefinition) {
+					if (isset($dataStructureSheetElementDefinition['type']) && $dataStructureSheetElementDefinition['type'] === 'array'
+						&& isset($dataStructureSheetElementDefinition['section']) && $dataStructureSheetElementDefinition['section'] === '1'
+					) {
+						// A section
+
+						// Existing section container elements
+						if (isset($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'])
+							&& is_array($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'])
+						) {
+							$containerArray = $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el'];
+							foreach ($containerArray as $aContainerNumber => $aContainerArray) {
+								if (is_array($aContainerArray)) {
+									foreach ($aContainerArray as $aContainerName => $aContainerElementArray) {
+										if ($aContainerName === '_TOGGLE') {
+											// Don't handle internal toggle state field
+											continue;
+										}
+										if (!isset($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName])) {
+											// Container not defined in ds
+											continue;
+										}
+										foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'][$aContainerName]['el'] as $singleFieldName => $singleFieldConfiguration) {
+											// $singleFieldValueArray = ['data']['sSections']['lDEF']['section_1']['el']['1']['container_1']['el']['element_1']
+											$singleFieldValueArray = [];
+											if (isset($aContainerElementArray['el'][$singleFieldName])
+												&& is_array($aContainerElementArray['el'][$singleFieldName])
+											) {
+												$singleFieldValueArray = $aContainerElementArray['el'][$singleFieldName];
+											}
+											foreach ($languagesOnElementLevel as $isoElementLevel) {
+												$langElementLevel = 'v' . $isoElementLevel;
+												$valueArray = [
+													'uid' => $result['databaseRow']['uid'],
+												];
+												$command = 'new';
+												if (array_key_exists($langElementLevel, $singleFieldValueArray)) {
+													$command = 'edit';
+													$valueArray[$singleFieldName] = $singleFieldValueArray[$langElementLevel];
+												}
+												$inputToFlexFormSegment = [
+													'tableName' => $result['tableName'],
+													'command' => $command,
+													// It is currently not possible to have pageTsConfig for section container
+													'pageTsConfigMerged' => [],
+													'databaseRow' => $valueArray,
+													'vanillaTableTca' => [
+														'ctrl' => [],
+														'columns' => [
+															$singleFieldName => $singleFieldConfiguration,
+														],
+													],
+													'processedTca' => [
+														'ctrl' => [],
+														'columns' => [
+															$singleFieldName => $singleFieldConfiguration,
+														],
+													],
+												];
+												$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
+												// Set data value result
+												if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
+													$result['databaseRow'][$fieldName]
+													['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['el']
+													[$aContainerNumber][$aContainerName]['el']
+													[$singleFieldName][$langElementLevel]
+														= $flexSegmentResult['databaseRow'][$singleFieldName];
+												}
+												// Set TCA structure result, actually, this call *might* be obsolete since the "dummy"
+												// handling below will set it again.
+												$result['processedTca']['columns'][$fieldName]['config']['ds']
+												['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
+												[$aContainerName]['el'][$singleFieldName]
+													= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
+											}
+										}
+									}
+								}
+							}
+						} // End of existing data value handling
+
+						// Prepare "fresh" row for every possible container
+						if (isset($dataStructureSheetElements[$dataStructureSheetElementName]['el']) && is_array($dataStructureSheetElements[$dataStructureSheetElementName]['el'])) {
+							foreach ($dataStructureSheetElements[$dataStructureSheetElementName]['el'] as $possibleContainerName => $possibleContainerConfiguration) {
+								if (isset($possibleContainerConfiguration['el']) && is_array($possibleContainerConfiguration['el'])) {
+									// Initialize result data array templateRows
+									$result['databaseRow'][$fieldName]
+									['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['templateRows']
+									[$possibleContainerName]['el']
+										= [];
+									foreach ($possibleContainerConfiguration['el'] as $singleFieldName => $singleFieldConfiguration) {
+										foreach ($languagesOnElementLevel as $isoElementLevel) {
+											$langElementLevel = 'v' . $isoElementLevel;
+											$inputToFlexFormSegment = [
+												'tableName' => $result['tableName'],
+												'command' => 'new',
+												'pageTsConfigMerged' => [],
+												'databaseRow' => [
+													'uid' => $result['databaseRow']['uid'],
+												],
+												'vanillaTableTca' => [
+													'ctrl' => [],
+													'columns' => [
+														$singleFieldName => $singleFieldConfiguration,
+													],
+												],
+												'processedTca' => [
+													'ctrl' => [],
+													'columns' => [
+														$singleFieldName => $singleFieldConfiguration,
+													],
+												],
+											];
+											$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
+											if (array_key_exists($singleFieldName, $flexSegmentResult['databaseRow'])) {
+												$result['databaseRow'][$fieldName]
+												['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName]['templateRows']
+												[$possibleContainerName]['el'][$singleFieldName][$langElementLevel]
+												 = $flexSegmentResult['databaseRow'][$singleFieldName];
+											}
+											$result['processedTca']['columns'][$fieldName]['config']['ds']
+											['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]['el']
+											[$possibleContainerName]['el'][$singleFieldName]
+												= $flexSegmentResult['processedTca']['columns'][$singleFieldName];
+										}
+									}
+								}
+							}
+						} // End of preparation for each possible container
+
+					// type without section is not ok
+					} elseif (isset($dataStructureSheetElementDefinition['type']) || isset($dataStructureSheetElementDefinition['section'])) {
+						throw new \UnexpectedValueException(
+							'Broken data structure on field name ' . $fieldName . '. section without type or vice versa is not allowed',
+							1440685208
+						);
+
+					// A "normal" TCA element
+					} else {
+						foreach ($languagesOnElementLevel as $isoElementLevel) {
+							$langElementLevel = 'v' . $isoElementLevel;
+							$valueArray = [
+								// uid of "parent" is given down for inline elements to resolve correctly
+								'uid' => $result['databaseRow']['uid'],
+							];
+							$command = 'new';
+							if (isset($dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName])
+								&& array_key_exists($langElementLevel, $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName])
+							) {
+								$command = 'edit';
+								$valueArray[$dataStructureSheetElementName] = $dataValues['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName][$langElementLevel];
+							}
+							$inputToFlexFormSegment = [
+								// tablename of "parent" is given down for inline elements to resolve correctly
+								'tableName' => $result['tableName'],
+								'command' => $command,
+								'pageTsConfigMerged' => $pageTsConfigMerged,
+								'databaseRow' => $valueArray,
+								'vanillaTableTca' => [
+									'ctrl' => [],
+									'columns' => [
+										$dataStructureSheetElementName => $dataStructureSheetElementDefinition,
+									],
+								],
+								'processedTca' => [
+									'ctrl' => [],
+									'columns' => [
+										$dataStructureSheetElementName => $dataStructureSheetElementDefinition,
+									],
+								],
+							];
+							$flexSegmentResult = $formDataCompiler->compile($inputToFlexFormSegment);
+							// Set data value result
+							if (array_key_exists($dataStructureSheetElementName, $flexSegmentResult['databaseRow'])) {
+								$result['databaseRow'][$fieldName]
+								['data'][$dataStructureSheetName][$langSheetLevel][$dataStructureSheetElementName][$langElementLevel]
+									= $flexSegmentResult['databaseRow'][$dataStructureSheetElementName];
+							}
+							// Set TCA structure result
+							$result['processedTca']['columns'][$fieldName]['config']['ds']
+							['sheets'][$dataStructureSheetName]['ROOT']['el'][$dataStructureSheetElementName]
+								= $flexSegmentResult['processedTca']['columns'][$dataStructureSheetElementName];
+						}
+					} // End of single element handling
+
+				}
+			}
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Modify data structure of a single "sheet"
+	 * Sets "secondary" data like sheet names and so on, but does NOT modify single elements
+	 *
+	 * @param array $dataStructure Given data structure
+	 * @param array $pageTsOfSheet Page Ts config of given field
+	 * @return array Modified data structure
+	 */
+	protected function modifySingleSheetInformation(array $dataStructure, array $pageTsOfSheet) {
+		// Return if no elements defined
+		if (!isset($dataStructure['ROOT']['el']) || !is_array($dataStructure['ROOT']['el'])) {
+			return $dataStructure;
+		}
+
+		// Rename sheet (tab)
+		if (!empty($pageTsOfSheet['sheetTitle'])) {
+			$dataStructure['ROOT']['sheetTitle'] = $pageTsOfSheet['sheetTitle'];
+		}
+		// Set sheet description (tab)
+		if (!empty($pageTsOfSheet['sheetDescription'])) {
+			$dataStructure['ROOT']['sheetDescription'] = $pageTsOfSheet['sheetDescription'];
+		}
+		// Set sheet short description (tab)
+		if (!empty($pageTsOfSheet['sheetShortDescr'])) {
+			$dataStructure['ROOT']['sheetShortDescr'] = $pageTsOfSheet['sheetShortDescr'];
+		}
+
+		return $dataStructure;
+	}
+
+	/**
+	 * Add new sheet languages not yet in data values and remove invalid ones
+	 *
+	 * databaseRow['aFlex']['data']['sDEF'] = array('lDEF', 'lNotAllowed');
+	 * allowedLanguageKeys = array('lDEF', 'lNEW')
+	 * -> databaseRow['aFlex']['data']['sDEF'] = array('lDEF', 'lNEW');
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @param array $allowedKeys List of allowed keys
+	 * @return array Modified result
+	 */
+	protected function setLanguageSheetsInDataValues(array $result, $fieldName, array $allowedKeys) {
+		$valueArray = [];
+		if (isset($result['databaseRow'][$fieldName]['data']) && is_array($result['databaseRow'][$fieldName]['data'])) {
+			$valueArray = $result['databaseRow'][$fieldName]['data'];
+		}
+		foreach ($valueArray as $sheetName => $sheetLanguages) {
+			// Add iso code with empty array if it does not yet exist in data
+			// and remove codes from data that do not exist in $allowed
+			$result['databaseRow'][$fieldName]['data'][$sheetName]
+				= array_intersect_key(array_merge($allowedKeys, $sheetLanguages), $allowedKeys);
+		}
+		return $result;
+	}
+
+	/**
+	 * Remove invalid keys from data value array the user has no access to
+	 * or that were removed or similar to prevent any rendering of this stuff
+	 *
+	 * Handles this for "normal" fields and also for section container element values.
+	 *
+	 * @param array $result Result array
+	 * @param string $fieldName Current handle field name
+	 * @param array $allowedKeys List of allowed keys
+	 * @return array Modified result
+	 */
+	protected function setLanguageValueLevelValues(array $result, $fieldName, $allowedKeys) {
+		$valueArray = [];
+		if (isset($result['databaseRow'][$fieldName]['data']) && is_array($result['databaseRow'][$fieldName]['data'])) {
+			$valueArray = $result['databaseRow'][$fieldName]['data'];
+		}
+		foreach ($valueArray as $sheetName => $sheetLanguages) {
+			if (!is_array($sheetLanguages)) {
+				continue;
+			}
+			foreach ($sheetLanguages as $languageName => $languageFields) {
+				if (!is_array($languageFields)) {
+					continue;
+				}
+				foreach ($languageFields as $flexFieldName => $fieldValues) {
+					if (!is_array($fieldValues)) {
+						continue;
+					}
+					$allowedSingleValues = [];
+					foreach ($fieldValues as $fieldValueName => $fieldValueValue) {
+						if (is_array($fieldValueValue) && $fieldValueName === 'el') {
+							// A section container
+							foreach ($fieldValueValue as $sectionNumber => $sectionElementArray) {
+								if (is_array($sectionElementArray)) {
+									$allowedSingleValues['el'][$sectionNumber] = [];
+									foreach ($sectionElementArray as $sectionElementName => $containerElementArray) {
+										if (isset($containerElementArray['el']) && is_array($containerElementArray['el']) && !empty($containerElementArray['el'])) {
+											foreach ($containerElementArray['el'] as $aContainerElementName => $aContainerElementValues) {
+												if (is_array($aContainerElementValues)) {
+													foreach ($aContainerElementValues as $aContainerElementValueKey => $aContainerElementValueValue) {
+														if (array_key_exists($aContainerElementValueKey, $allowedKeys)) {
+															$allowedSingleValues['el'][$sectionNumber][$sectionElementName]
+															['el'][$aContainerElementName][$aContainerElementValueKey] = $aContainerElementValueValue;
+														}
+													}
+												} else {
+													$allowedSingleValues['el'][$sectionNumber][$sectionElementName]['el']
+													[$aContainerElementName] = $aContainerElementValues;
+												}
+											}
+										} else {
+											$allowedSingleValues['el'][$sectionNumber][$sectionElementName] = $containerElementArray;
+										}
+									}
+								} else {
+									$allowedSingleValues = $sectionElementArray;
+								}
+							}
+						} else {
+							// "normal" value field
+							if (array_key_exists($fieldValueName, $allowedKeys)) {
+								$allowedSingleValues[$fieldValueName] = $fieldValueValue;
+							}
+						}
+					}
+					$result['databaseRow'][$fieldName]['data'][$sheetName][$languageName][$flexFieldName] = $allowedSingleValues;
+				}
+			}
+		}
+		return $result;
+	}
+
+	/**
+	 * @return BackendUserAuthentication
+	 */
+	protected function getBackendUser() {
+		return $GLOBALS['BE_USER'];
+	}
+
+}
diff --git a/typo3/sysext/compatibility6/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php b/typo3/sysext/compatibility6/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php
new file mode 100644
index 000000000000..67a6d94fc4fd
--- /dev/null
+++ b/typo3/sysext/compatibility6/Tests/Unit/Form/FormDataProvider/TcaFlexProcessTest.php
@@ -0,0 +1,2397 @@
+<?php
+namespace TYPO3\CMS\Compatibility6\Tests\Unit\Form\FormDataProvider;
+
+/*
+ * 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!
+ */
+
+use Prophecy\Argument;
+use Prophecy\Prophecy\ObjectProphecy;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+use TYPO3\CMS\Compatibility6\Form\FormDataProvider\TcaFlexProcess;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Lang\LanguageService;
+
+/**
+ * Test case
+ */
+class TcaFlexProcessTest extends UnitTestCase {
+
+	/**
+	 * @var TcaFlexProcess
+	 */
+	protected $subject;
+
+	/**
+	 * @var BackendUserAuthentication|ObjectProphecy
+	 */
+	protected $backendUserProphecy;
+
+	protected function setUp() {
+		/** @var BackendUserAuthentication|ObjectProphecy backendUserProphecy */
+		$this->backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
+		$GLOBALS['BE_USER'] = $this->backendUserProphecy->reveal();
+		$GLOBALS['BE_USER']->groupData['non_exclude_fields'] = '';
+
+		// Some tests call FormDataCompiler for sub elements. Those tests have functional test characteristics.
+		// This is ok for the time being, but this settings takes care only parts of the compiler are called
+		// to have less dependencies.
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [];
+
+		$this->subject = new TcaFlexProcess();
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataOverwritesDataStructureLangDisableIfSetViaPageTsConfig() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'langDisable' => 1,
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [],
+			'langDisable' => TRUE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataOverwritesDataStructureLangChildrenIfSetViaPageTsConfig() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'langChildren' => FALSE,
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [],
+			'langDisable' => FALSE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataRemovesSheetIfDisabledByPageTsConfig() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'aSheet' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'aSheet.' => [
+									'disabled' => 1,
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsSheetTitleFromPageTsConfig() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'aSheet' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'aSheet.' => [
+									'sheetTitle' => 'aTitle',
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'aSheet' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'input',
+								],
+							],
+						],
+						'sheetTitle' => 'aTitle',
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsSheetDescriptionFromPageTsConfig() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'aSheet' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'aSheet.' => [
+									'sheetDescription' => 'aDescription',
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'aSheet' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'input',
+								],
+							],
+						],
+						'sheetDescription' => 'aDescription',
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsSheetShortDescriptionFromPageTsConfig() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'aSheet' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'aSheet.' => [
+									'sheetDescription' => 'sheetShortDescr',
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'aSheet' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'input',
+								],
+							],
+						],
+						'sheetDescription' => 'sheetShortDescr',
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsSheetShortDescriptionForSingleSheetFromPageTsConfig() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'sDEF.' => [
+									'sheetDescription' => 'sheetShortDescr',
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'sDEF' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'input',
+								],
+							],
+						],
+						'sheetDescription' => 'sheetShortDescr',
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataRemovesExcludeFieldFromDataStructure() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'exclude' => '1',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$this->backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(FALSE);
+		$GLOBALS['BE_USER']->groupData['non_exclude_fields'] = '';
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'sDEF' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [],
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataKeepsExcludeFieldInDataStructureWithUserAccess() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'exclude' => '1',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$this->backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(FALSE);
+		$GLOBALS['BE_USER']->groupData['non_exclude_fields'] = 'aTable:aField;aFlex;sDEF;aFlexField';
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'sDEF' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'input',
+								],
+								'exclude' => '1',
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataKeepsExcludeFieldInDataStructureForAdminUser() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'exclude' => '1',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$this->backendUserProphecy->isAdmin()->shouldBeCalled()->willReturn(TRUE);
+		$GLOBALS['BE_USER']->groupData['non_exclude_fields'] = '';
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'sDEF' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'input',
+								],
+								'exclude' => '1',
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataRemovesPageTsDisabledFieldFromDataStructure() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+													],
+												]
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'sDEF.' => [
+									'aFlexField.' => [
+										'disabled' => 1,
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'sDEF' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [],
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataCleansLanguageDisabledDataValues() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'input_1' => [
+									'vDEF' => 'input1 text',
+									'vDEF.vDEFbase' => 'base',
+									'_TRANSFORM_vDEF.vDEFbase' => 'transform',
+									'vRemoveMe' => 'removeMe',
+									'vRemoveMe.vDEFbase' => 'removeMe',
+									'_TRANSFORM_vRemoveMe.vDEFbase' => 'removeMe',
+								],
+								'section_1' => [
+									'el' => [
+										'1' => [
+											'container_1' => [
+												'el' => [
+													'input_2' => [
+														'vDEF' => 'input2 text',
+														'vRemoveMe' => 'removeMe',
+													]
+												],
+											],
+										],
+									],
+								],
+								'invalid1' => 'keepMe',
+								'invalid2' => [
+									'el' => [
+										'1' => [
+											'keepMe',
+										],
+									],
+								],
+								'invalid3' => [
+									'el' => [
+										'1' => [
+											'container_2' => 'keepMe',
+										],
+									],
+								],
+								'invalid4' => [
+									'el' => [
+										'1' => [
+											'container_2' => [
+												'el' => 'keepMe',
+											],
+										],
+									],
+								],
+								'invalid5' => [
+									'el' => [
+										'1' => [
+											'container_2' => [
+												'el' => [
+													'field' => 'keepMe',
+												],
+											],
+										],
+									],
+								],
+							],
+							'lRemoveMe' => [],
+						],
+					],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'title' => 'aLanguageTitle',
+					'iso' => 'DEF',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'meta' => [
+									'langDisable' => 1,
+								],
+								'sheets' => [],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+			],
+			'langDisable' => TRUE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lRemoveMe']);
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vRemoveMe']);
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vRemoveMe.vDEFbase']);
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['_TRANSFORM_vRemoveMe.vDEFbase']);
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['input_2']['vRemoveMe']);
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataRemovesDataValuesIfUserHasNoAccess() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'input_1' => [
+									'vDEF' => 'input1 text',
+								],
+								'section_1' => [
+									'el' => [
+										'1' => [
+											'container_1' => [
+												'el' => [
+													'input_2' => [
+														'vDEF' => 'input2 text',
+														'vNoAccess' => 'removeMe',
+													]
+												],
+											],
+										],
+									],
+								],
+							],
+							'lNoAccess' => [],
+						],
+					],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'NoAccess',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'meta' => [
+									'langDisable' => 0,
+								],
+								'sheets' => [],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(FALSE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lNoAccess']);
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['input_2']['vNoAccess']);
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataAddsNewLanguageDataValues() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'input_1' => [
+									'vDEF' => 'input1 text',
+								],
+							],
+						],
+					],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'meta' => [
+									'langDisable' => 0,
+								],
+								'sheets' => [],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		$expected['databaseRow']['aField']['data']['sDEF']['lEN'] = [];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataRemovesDataValuesIfPageOverlayCheckIsEnabled() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [],
+							'lEN' => [],
+							'lNoOverlay' => [],
+						],
+					],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+				2 => [
+					'uid' => 2,
+					'iso' => 'NoOverlay',
+				],
+			],
+			'userTsConfig' => [
+				'options.' => [
+					'checkPageLanguageOverlay' => '1',
+				],
+			],
+			'pageLanguageOverlayRows' => [
+				0 => [
+					'uid' => 1,
+					'sys_language_uid' => 1,
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'meta' => [
+									'langDisable' => 0,
+								],
+								'sheets' => [],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('2')->shouldBeCalled()->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lNoOverlay']);
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataRemovesLanguageDataValuesIfUserHasNoAccessWithLangChildren() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'input_1' => [
+									'vDEF' => 'input1 text',
+									'vNoAccess' => 'removeMe',
+								],
+								'section_1' => [
+									'el' => [
+										'1' => [
+											'container_1' => [
+												'el' => [
+													'input_2' => [
+														'vDEF' => 'input2 text',
+														'vNoAccess' => 'removeMe',
+													]
+												],
+											],
+										],
+									],
+								],
+							],
+							'lNoAccess' => [],
+						],
+					],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'NoAccess',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'meta' => [
+									'langDisable' => 0,
+									'langChildren' => 1,
+								],
+								'sheets' => [],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(FALSE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => TRUE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lNoAccess']);
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vNoAccess']);
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['input_2']['vNoAccess']);
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataRemovesDataValuesIfPageOverlayCheckIsEnabledWithLangChildren() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'input_1' => [
+									'vDEF' => 'input1 text',
+									'vEN' => 'input1 en text',
+									'vNoOverlay' => 'removeMe',
+								],
+							],
+						],
+					],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+				2 => [
+					'uid' => 2,
+					'iso' => 'NoOverlay',
+				],
+			],
+			'userTsConfig' => [
+				'options.' => [
+					'checkPageLanguageOverlay' => '1',
+				],
+			],
+			'pageLanguageOverlayRows' => [
+				0 => [
+					'uid' => 1,
+					'sys_language_uid' => 1,
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'meta' => [
+									'langDisable' => 0,
+									'langChildren' => 1,
+								],
+								'sheets' => [],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('0')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('1')->shouldBeCalled()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess('2')->shouldBeCalled()->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => TRUE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+				1 => 'EN',
+			]
+		];
+
+		unset($expected['databaseRow']['aField']['data']['sDEF']['lDEF']['input_1']['vNoOverlay']);
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataHandlesPageTsConfigSettingsOfSingleFlexField() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'meta' => [
+									'langDisable' => 0,
+									'langChildren' => 0,
+								],
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'radio',
+														'items' => [
+															0 => [
+																0 => 'aLabel',
+																1 => 'aValue',
+															],
+														],
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [
+				'TCEFORM.' => [
+					'aTable.' => [
+						'aField.' => [
+							'aFlex.' => [
+								'sDEF.' => [
+									'aFlexField.' => [
+										'altLabels.' => [
+											'0' => 'labelOverride',
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [],
+		];
+
+		/** @var LanguageService|ObjectProphecy $languageService */
+		$languageService = $this->prophesize(LanguageService::class);
+		$GLOBALS['LANG'] = $languageService->reveal();
+		$languageService->sL(Argument::cetera())->willReturnArgument(0);
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds'] = [
+			'meta' => [
+				'availableLanguageCodes' => [
+					0 => 'DEF',
+				],
+				'langDisable' => FALSE,
+				'langChildren' => FALSE,
+				'languagesOnSheetLevel' => [
+					0 => 'DEF',
+				],
+				'languagesOnElement' => [
+					0 => 'DEF',
+				]
+			],
+			'sheets' => [
+				'sDEF' => [
+					'ROOT' => [
+						'type' => 'array',
+						'el' => [
+							'aFlexField' => [
+								'label' => 'aFlexFieldLabel',
+								'config' => [
+									'type' => 'radio',
+									'items' => [
+										0 => [
+											0 => 'labelOverride',
+											1 => 'aValue',
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+		];
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsDefaultValueFromFlexTcaForField() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+														'default' => 'defaultValue',
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
+		];
+
+		/** @var LanguageService|ObjectProphecy $languageService */
+		$languageService = $this->prophesize(LanguageService::class);
+		$GLOBALS['LANG'] = $languageService->reveal();
+		$languageService->sL(Argument::cetera())->willReturnArgument(0);
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vDEF'] = 'defaultValue';
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsDefaultValueFromFlexTcaForFieldInLocalizedSheet() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+														'default' => 'defaultValue',
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
+		];
+
+		/** @var LanguageService|ObjectProphecy $languageService */
+		$languageService = $this->prophesize(LanguageService::class);
+		$GLOBALS['LANG'] = $languageService->reveal();
+		$languageService->sL(Argument::cetera())->willReturnArgument(0);
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF'
+			]
+		];
+
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vDEF'] = 'defaultValue';
+		$expected['databaseRow']['aField']['data']['sDEF']['lEN']['aFlexField']['vDEF'] = 'defaultValue';
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsDefaultValueFromFlexTcaForFieldInLocalizedSheetWithLangChildren() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds' => [
+								'meta' => [
+									'langChildren' => 1,
+								],
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'label' => 'aFlexFieldLabel',
+													'config' => [
+														'type' => 'input',
+														'default' => 'defaultValue',
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
+		];
+
+		/** @var LanguageService|ObjectProphecy $languageService */
+		$languageService = $this->prophesize(LanguageService::class);
+		$GLOBALS['LANG'] = $languageService->reveal();
+		$languageService->sL(Argument::cetera())->willReturnArgument(0);
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => TRUE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+				1 => 'EN'
+			]
+		];
+
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vDEF'] = 'defaultValue';
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['aFlexField']['vEN'] = 'defaultValue';
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataThrowsExceptionForDataStructureTypeArrayWithoutSection() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'type' => 'array',
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1440685208);
+
+		$this->subject->addData($input);
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataThrowsExceptionForDataStructureSectionWithoutTypeArray() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [],
+					'meta' => [],
+				],
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'aFlexField' => [
+													'section' => '1',
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$this->setExpectedException(\UnexpectedValueException::class, $this->anything(), 1440685208);
+
+		$this->subject->addData($input);
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsValuesAndStructureForSectionContainerElementsNoLangChildren() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'section_1' => [
+									'el' => [
+										'1' => [
+											'container_1' => [
+												// It should set the default value for aFlexField here
+												'el' => [
+												],
+											],
+										],
+										'2' => [
+											'container_1' => [
+												'el' => [
+													'aFlexField' => [
+														// It should keep this value
+														'vDEF' => 'dbValue',
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+							'lEN' => [
+								'section_1' => [
+									'el' => [
+										'1' => [
+											'container_1' => [
+												// It should add the default value for aFlexField here
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+					'meta' => [],
+				],
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds' => [
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'section_1' => [
+													'section' => '1',
+													'type' => 'array',
+													'el' => [
+														'container_1' => [
+															'type' => 'array',
+															'el' => [
+																'aFlexField' => [
+																	'label' => 'aFlexFieldLabel',
+																	'config' => [
+																		'type' => 'input',
+																		'default' => 'defaultValue',
+																	],
+																],
+															],
+														],
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
+		];
+
+		/** @var LanguageService|ObjectProphecy $languageService */
+		$languageService = $this->prophesize(LanguageService::class);
+		$GLOBALS['LANG'] = $languageService->reveal();
+		$languageService->sL(Argument::cetera())->willReturnArgument(0);
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => FALSE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+			]
+		];
+
+		// A default value for existing container field aFlexField should have been set
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
+		// Also for the other defined language
+		$expected['databaseRow']['aField']['data']['sDEF']['lEN']['section_1']['el']['1']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
+
+		// Dummy row values for container_1 on lDEF sheet
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['templateRows']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
+		// Dummy row values for container_1 on lDEF sheet
+		$expected['databaseRow']['aField']['data']['sDEF']['lEN']['section_1']['templateRows']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+	/**
+	 * @test
+	 */
+	public function addDataSetsValuesAndStructureForSectionContainerElementsWithLangChildren() {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'section_1' => [
+									'el' => [
+										'1' => [
+											'container_1' => [
+												// It should set a default for both vDEF and vEN
+												'el' => [
+												],
+											],
+										],
+										'2' => [
+											'container_1' => [
+												'el' => [
+													'aFlexField' => [
+														// It should keep this value
+														'vDEF' => 'dbValue',
+														// It should set a default for vEN
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+					'meta' => [],
+				],
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds' => [
+								'meta' => [
+									'langChildren' => 1,
+								],
+								'sheets' => [
+									'sDEF' => [
+										'ROOT' => [
+											'type' => 'array',
+											'el' => [
+												'section_1' => [
+													'section' => '1',
+													'type' => 'array',
+													'el' => [
+														'container_1' => [
+															'type' => 'array',
+															'el' => [
+																'aFlexField' => [
+																	'label' => 'aFlexFieldLabel',
+																	'config' => [
+																		'type' => 'input',
+																		'default' => 'defaultValue',
+																	],
+																],
+															],
+														],
+													],
+												],
+											],
+										],
+									],
+								],
+							],
+						],
+					],
+				],
+			],
+			'pageTsConfigMerged' => [],
+		];
+
+		$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['flexFormSegment'] = [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => [],
+		];
+
+		/** @var LanguageService|ObjectProphecy $languageService */
+		$languageService = $this->prophesize(LanguageService::class);
+		$GLOBALS['LANG'] = $languageService->reveal();
+		$languageService->sL(Argument::cetera())->willReturnArgument(0);
+
+		$this->backendUserProphecy->isAdmin()->willReturn(TRUE);
+		$this->backendUserProphecy->checkLanguageAccess(Argument::cetera())->willReturn(TRUE);
+
+		$expected = $input;
+		$expected['processedTca']['columns']['aField']['config']['ds']['meta'] = [
+			'availableLanguageCodes' => [
+				0 => 'DEF',
+				1 => 'EN',
+			],
+			'langDisable' => FALSE,
+			'langChildren' => TRUE,
+			'languagesOnSheetLevel' => [
+				0 => 'DEF',
+			],
+			'languagesOnElement' => [
+				0 => 'DEF',
+				1 => 'EN',
+			]
+		];
+
+		// A default value for existing container field aFlexField should have been set
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['1']['container_1']['el']['aFlexField']['vEN'] = 'defaultValue';
+		// Also for the other defined language
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['el']['2']['container_1']['el']['aFlexField']['vEN'] = 'defaultValue';
+
+		// There should be a templateRow for container_1 with defaultValue set for both languages
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['templateRows']['container_1']['el']['aFlexField']['vDEF'] = 'defaultValue';
+		$expected['databaseRow']['aField']['data']['sDEF']['lDEF']['section_1']['templateRows']['container_1']['el']['aFlexField']['vEN'] = 'defaultValue';
+
+		$this->assertEquals($expected, $this->subject->addData($input));
+	}
+
+
+	/**
+	 * Date provider for addDataSetsLanguageFlags
+	 *
+	 * @return array
+	 */
+	public function addDataSetsLanguageFlagsDataProvider() {
+		return [
+			'Default values are set' => [
+				'sheets' => [
+					'sDEF' => [
+						'ROOT' => [],
+					],
+				],
+				FALSE,
+				FALSE,
+				[],
+				[0 => 'DEF'],
+			],
+			'langDisable is set to FALSE' => [
+				'sheets' => [
+					'meta' => [
+						'langDisable' => 0,
+					],
+					'sDEF' => [
+						'ROOT' => [],
+					],
+				],
+				FALSE,
+				FALSE,
+				[],
+				[0 => 'DEF'],
+			],
+			'langDisable is set to TRUE' => [
+				'sheets' => [
+					'meta' => [
+						'langDisable' => 1,
+					],
+					'sDEF' => [
+						'ROOT' => [],
+					],
+				],
+				TRUE,
+				FALSE,
+				[],
+				[0 => 'DEF'],
+			],
+			'langChildren is set to FALSE' => [
+				'sheets' => [
+					'meta' => [
+						'langChildren' => 0,
+					],
+					'sDEF' => [
+						'ROOT' => [],
+					],
+				],
+				FALSE,
+				FALSE,
+				[],
+				[0 => 'DEF'],
+			],
+			'langChildren is set to TRUE' => [
+				'sheets' => [
+					'meta' => [
+						'langChildren' => 1,
+					],
+					'sDEF' => [
+						'ROOT' => [],
+					],
+				],
+				FALSE,
+				TRUE,
+				[0 => 'DEF'],
+				[],
+			],
+			'langDisable and langChildren are set' => [
+				'sheets' => [
+					'meta' => [
+						'langDisable' => 1,
+						'langChildren' => 1,
+					],
+					'sDEF' => [
+						'ROOT' => [],
+					],
+				],
+				TRUE,
+				TRUE,
+				[0 => 'DEF'],
+				[],
+			],
+		];
+	}
+
+	/**
+	 * @test
+	 * @param $flexform
+	 * @param $expectedLangDisable
+	 * @param $expectedLangChildren
+	 * @param $expectedLanguagesOnSheetLevel
+	 * @param $expectedLanguagesOnElement
+	 * @dataProvider addDataSetsLanguageFlagsDataProvider
+	 */
+	public function addDataSetsLanguageFlags($flexform, $expectedLangDisable, $expectedLangChildren, $expectedLanguagesOnSheetLevel, $expectedLanguagesOnElement) {
+		$input = [
+			'tableName' => 'aTable',
+			'databaseRow' => [
+				'aField' => [
+					'data' => [
+						'sDEF' => [
+							'lDEF' => [
+								'input_1' => [
+									'vDEF' => 'input1 text',
+								],
+							],
+						],
+					],
+					'meta' => [],
+				],
+				'pointerField' => 'aFlex',
+			],
+			'systemLanguageRows' => [
+				0 => [
+					'uid' => 0,
+					'iso' => 'DEF',
+				],
+				1 => [
+					'uid' => 1,
+					'iso' => 'EN',
+				],
+			],
+			'processedTca' => [
+				'columns' => [
+					'aField' => [
+						'config' => [
+							'type' => 'flex',
+							'ds_pointerField' => 'pointerField',
+							'ds' => $flexform,
+						],
+					],
+				],
+			],
+		];
+
+		$result = $this->subject->addData($input);
+
+		$this->assertEquals($expectedLangDisable, $result['processedTca']['columns']['aField']['config']['ds']['meta']['langDisable']);
+		$this->assertEquals($expectedLangChildren, $result['processedTca']['columns']['aField']['config']['ds']['meta']['langChildren']);
+		$this->assertEquals($expectedLanguagesOnSheetLevel, $result['processedTca']['columns']['aField']['config']['ds']['meta']['languagesOnSheetLevel']);
+		$this->assertEquals($expectedLanguagesOnElement, $result['processedTca']['columns']['aField']['config']['ds']['meta']['languagesOnElement']);
+	}
+
+}
diff --git a/typo3/sysext/compatibility6/ext_localconf.php b/typo3/sysext/compatibility6/ext_localconf.php
index e520c99371af..e1e4c3945b76 100644
--- a/typo3/sysext/compatibility6/ext_localconf.php
+++ b/typo3/sysext/compatibility6/ext_localconf.php
@@ -10,6 +10,52 @@ if (!$_EXTCONF || $_EXTCONF['setPageTSconfig']) {
 	');
 }
 
+
+// Register language aware flex form handling in FormEngine
+// Register render elements
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1443361297] = [
+	'nodeName' => 'flex',
+	'priority' => 40,
+	'class' => \TYPO3\CMS\Compatibility6\Form\Container\FlexFormEntryContainer::class,
+];
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1443361298] = [
+	'nodeName' => 'flexFormNoTabsContainer',
+	'priority' => 40,
+	'class' => \TYPO3\CMS\Compatibility6\Form\Container\FlexFormNoTabsContainer::class,
+];
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1443361299] = [
+	'nodeName' => 'flexFormTabsContainer',
+	'priority' => 40,
+	'class' => \TYPO3\CMS\Compatibility6\Form\Container\FlexFormTabsContainer::class,
+];
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1443361300] = [
+	'nodeName' => 'flexFormElementContainer',
+	'priority' => 40,
+	'class' => \TYPO3\CMS\Compatibility6\Form\Container\FlexFormElementContainer::class,
+];
+// Unregister stock TcaFlexProcess data provider and substitute with own data provider at the same position
+unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRecord']
+	[\TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexProcess::class]
+);
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRecord']
+	[\TYPO3\CMS\Compatibility6\Form\FormDataProvider\TcaFlexProcess::class] = [
+		'depends' => [
+			\TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexPrepare::class,
+		]
+	];
+unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRecord']
+	[\TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class]['depends'][\TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexProcess::class]
+);
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRecord']
+	[\TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class]['depends'][]
+		= \TYPO3\CMS\Compatibility6\Form\FormDataProvider\TcaFlexProcess::class;
+// Register "XCLASS" of FlexFormTools for language parsing
+$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools::class]['className']
+	= TYPO3\CMS\Compatibility6\Configuration\FlexForm\FlexFormTools::class;
+// Language diff updating in flex
+$GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] = TRUE;
+
+
 // TCA migration if TCA registration still happened in ext_tables.php
 if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing'])) {
 	$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['extTablesInclusion-PostProcessing'] = array();
diff --git a/typo3/sysext/core/Classes/Configuration/FlexForm/FlexFormTools.php b/typo3/sysext/core/Classes/Configuration/FlexForm/FlexFormTools.php
index 9d99b36d1fc8..6615235696f5 100644
--- a/typo3/sysext/core/Classes/Configuration/FlexForm/FlexFormTools.php
+++ b/typo3/sysext/core/Classes/Configuration/FlexForm/FlexFormTools.php
@@ -118,27 +118,6 @@ class FlexFormTools {
 			if (!is_array($editData)) {
 				return 'Parsing error: ' . $editData;
 			}
-			// Language settings:
-			$langChildren = $dataStructArray['meta']['langChildren'] ? 1 : 0;
-			$langDisabled = $dataStructArray['meta']['langDisable'] ? 1 : 0;
-			// Empty or invalid <meta>
-			if (!is_array($editData['meta'])) {
-				$editData['meta'] = array();
-			}
-			$editData['meta']['currentLangId'] = array();
-			$languages = $this->getAvailableLanguages();
-			foreach ($languages as $lInfo) {
-				$editData['meta']['currentLangId'][] = $lInfo['ISOcode'];
-			}
-			if (empty($editData['meta']['currentLangId'])) {
-				$editData['meta']['currentLangId'] = array('DEF');
-			}
-			$editData['meta']['currentLangId'] = array_unique($editData['meta']['currentLangId']);
-			if ($langChildren || $langDisabled) {
-				$lKeys = array('DEF');
-			} else {
-				$lKeys = $editData['meta']['currentLangId'];
-			}
 			// Tabs sheets
 			if (is_array($dataStructArray['sheets'])) {
 				$sKeys = array_keys($dataStructArray['sheets']);
@@ -146,27 +125,22 @@ class FlexFormTools {
 				$sKeys = array('sDEF');
 			}
 			// Traverse languages:
-			foreach ($lKeys as $lKey) {
-				foreach ($sKeys as $sheet) {
-					$sheetCfg = $dataStructArray['sheets'][$sheet];
-					list($dataStruct, $sheet) = GeneralUtility::resolveSheetDefInDS($dataStructArray, $sheet);
-					// Render sheet:
-					if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) {
-						// Separate language key
-						$lang = 'l' . $lKey;
-						$PA['vKeys'] = $langChildren && !$langDisabled ? $editData['meta']['currentLangId'] : array('DEF');
-						$PA['lKey'] = $lang;
-						$PA['callBackMethod_value'] = $callBackMethod_value;
-						$PA['table'] = $table;
-						$PA['field'] = $field;
-						$PA['uid'] = $row['uid'];
-						$this->traverseFlexFormXMLData_DS = &$dataStruct;
-						$this->traverseFlexFormXMLData_Data = &$editData;
-						// Render flexform:
-						$this->traverseFlexFormXMLData_recurse($dataStruct['ROOT']['el'], $editData['data'][$sheet][$lang], $PA, 'data/' . $sheet . '/' . $lang);
-					} else {
-						return 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".';
-					}
+			foreach ($sKeys as $sheet) {
+				list($dataStruct, $sheet) = GeneralUtility::resolveSheetDefInDS($dataStructArray, $sheet);
+				// Render sheet:
+				if (is_array($dataStruct['ROOT']) && is_array($dataStruct['ROOT']['el'])) {
+					$PA['vKeys'] = array('DEF');
+					$PA['lKey'] = 'lDEF';
+					$PA['callBackMethod_value'] = $callBackMethod_value;
+					$PA['table'] = $table;
+					$PA['field'] = $field;
+					$PA['uid'] = $row['uid'];
+					$this->traverseFlexFormXMLData_DS = &$dataStruct;
+					$this->traverseFlexFormXMLData_Data = &$editData;
+					// Render flexform:
+					$this->traverseFlexFormXMLData_recurse($dataStruct['ROOT']['el'], $editData['data'][$sheet]['lDEF'], $PA, 'data/' . $sheet . '/lDEF');
+				} else {
+					return 'Data Structure ERROR: No ROOT element found for sheet "' . $sheet . '".';
 				}
 			}
 		} else {
@@ -249,8 +223,10 @@ class FlexFormTools {
 	 * Returns an array of available languages to use for FlexForm operations
 	 *
 	 * @return array
+	 * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8
 	 */
 	public function getAvailableLanguages() {
+		GeneralUtility::logDeprecatedFunction();
 		$isL = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('static_info_tables');
 		// Find all language records in the system
 		$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
@@ -324,13 +300,6 @@ class FlexFormTools {
 	public function cleanFlexFormXML_callBackFunction($dsArr, $data, $PA, $path, $pObj) {
 		// Just setting value in our own result array, basically replicating the structure:
 		$pObj->setArrayValueByPath($path, $this->cleanFlexFormXML, $data);
-		// Looking if an "extension" called ".vDEFbase" is found and if so, accept that too:
-		if ($GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase']) {
-			$vDEFbase = $pObj->getArrayValueByPath($path . '.vDEFbase', $pObj->traverseFlexFormXMLData_Data);
-			if (isset($vDEFbase)) {
-				$pObj->setArrayValueByPath($path . '.vDEFbase', $this->cleanFlexFormXML, $vDEFbase);
-			}
-		}
 	}
 
 	/***********************************
diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
index 256e719fd507..c43ccd305a56 100644
--- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php
+++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
@@ -141,6 +141,7 @@ class DataHandler {
 	 * If set, .vDEFbase values are unset in flexforms.
 	 *
 	 * @var bool
+	 * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8
 	 */
 	public $clear_flexFormData_vDEFbase = FALSE;
 
@@ -2448,6 +2449,7 @@ class DataHandler {
 				$currentValueArray = array();
 			}
 			if (isset($currentValueArray['meta']['currentLangId'])) {
+				// @deprecated call since TYPO3 7, will be removed with TYPO3 8
 				unset($currentValueArray['meta']['currentLangId']);
 			}
 			// Remove all old meta for languages...
@@ -3078,6 +3080,7 @@ class DataHandler {
 					// Finally, check if new and old values are different (or no .vDEFbase value is found) and if so, we record the vDEF value for diff'ing.
 					// We do this after $dataValues has been updated since I expect that $dataValues_current holds evaluated values from database (so this must be the right value to compare with).
 					if (substr($vKey, -9) != '.vDEFbase') {
+						// @deprecated: flexFormXMLincludeDiffBase is only enabled by ext:compatibility6 since TYPO3 CMS 7, vDEFbase can be unset / ignored with TYPO3 CMS 8
 						if ($this->clear_flexFormData_vDEFbase) {
 							$dataValues[$key][$vKey . '.vDEFbase'] = '';
 						} elseif ($this->updateModeL10NdiffData && $GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && $vKey !== 'vDEF' && ((string)$dataValues[$key][$vKey] !== (string)$dataValues_current[$key][$vKey] || !isset($dataValues_current[$key][($vKey . '.vDEFbase')]) || $this->updateModeL10NdiffData === 'FORCE_FFUPD')) {
diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php
index 066c833f0b5e..96a4917e4eab 100644
--- a/typo3/sysext/core/Configuration/DefaultConfiguration.php
+++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php
@@ -860,7 +860,6 @@ return array(
 		'notificationPrefix' => '[TYPO3 Note]',				// String: Used to prefix the subject of mails sent in the taskcenter
 		'explicitADmode' => 'explicitDeny',					// Sets the general allow/deny mode for selector box values. Value can be either "explicitAllow" or "explicitDeny", nothing else!
 		'niceFlexFormXMLtags' => TRUE,						// If set, the flexform XML will be stored with meaningful tags which can be validated with DTD schema. If you rely on custom reading of the XML from pre-4.0 versions you should set this to FALSE if you don't like to change your reader code (internally it is insignificant since \TYPO3\CMS\Core\Utility\GeneralUtility::xml2array() doesn't care for the tags if the index-attribute value is set)
-		'flexFormXMLincludeDiffBase' => TRUE,				// If set, an additional tag with index "vXX.vDEFbase" is created for translations in flexforms holding the value of the default language when translation was changed. Used to show diff of value. This setting will change whether the system thinks flexform XML looks clean. For example when FALSE XX.vDEFbase fields will be removed in cleaning while accepted if TRUE (of course)
 		'compactFlexFormXML' => 0,							// If set, the flexform XML will not contain indentation spaces making XML more compact
 		'flexformForceCDATA' => 0,							// Boolean:  If set, will add CDATA to Flexform XML. Some versions of libxml have a bug that causes HTML entities to be stripped from any XML content and this setting will avoid the bug by adding CDATA.
 		'explicitConfirmationOfTranslation' => FALSE,		// If set, then the diff-data of localized records is not saved automatically when updated but requires that a translator clicks the special finish_translation/save/close button that becomes available.
diff --git a/typo3/sysext/core/Configuration/Resource/Driver/LocalDriverFlexForm.xml b/typo3/sysext/core/Configuration/Resource/Driver/LocalDriverFlexForm.xml
index 4616ef60a49a..3c6d9ef6b854 100644
--- a/typo3/sysext/core/Configuration/Resource/Driver/LocalDriverFlexForm.xml
+++ b/typo3/sysext/core/Configuration/Resource/Driver/LocalDriverFlexForm.xml
@@ -1,8 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <T3DataStructure>
-	<meta>
-		<langDisable>1</langDisable>
-	</meta>
 	<ROOT>
 		<type>array</type>
 		<el>
@@ -47,4 +44,4 @@
 			</caseSensitive>
 		</el>
 	</ROOT>
-</T3DataStructure>
\ No newline at end of file
+</T3DataStructure>
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-70138-FlexFormLanguageHandling.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-70138-FlexFormLanguageHandling.rst
new file mode 100644
index 000000000000..c4df09487fc4
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-70138-FlexFormLanguageHandling.rst
@@ -0,0 +1,83 @@
+=================================================
+Deprecation: #70138 - Flex form language handling
+=================================================
+
+Description
+===========
+
+``TCA`` flex fields had an own language handling that allowed to store field localization within
+the flex data itself and not within the usual database driven overlay records. This was mainly
+introduced for ``TemplaVoila`` and usually only used in this context.
+
+The whole flex form specific language handling has been moved from core extensions to extension
+``compatibility6`` and will not be delivered with ``TYPO3 CMS 7 LTS`` anymore.
+
+The following flex XML data structure keys have been deprecated and are supported by ``compatiblity6`` only:
+
+* ``<meta><langDisable>``
+* ``<meta><langChildren>``
+* ``<meta><currentLangId>``
+
+
+The following ``Page TS config`` options have been dropped and are ignored if ``compatibility6`` is not loaded:
+
+* ``TCEFORM.[tableName].[field].[dataStructureKey].langDisable``
+* ``TCEFORM.[tableName].[field].[dataStructureKey].langChildren``
+
+
+The following ``User TS config`` options have been dropped and are ignored if ``compatibility6`` is not loaded:
+
+* ``options.checkPageLanguageOverlay``
+
+
+The following ``LocalConfiguration`` value has been deprecated, will be removed by the install tool and
+is set by ``compatibility6`` to ``TRUE``:
+
+* ``$GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase']``
+
+
+The following method has been marked as deprecated and is cloned by ``compatibility6`` in an ``XCLASS``:
+
+* ``TYPO3\CMS\Core\Configaration\FlexForm\FlexFormTools->getAvailableLanguages()``
+
+
+The following property has been marked as deprecated:
+
+* ``TYPO3\CMS\Core\DataHandling\DataHandler->clear_flexFormData_vDEFbase``
+
+
+Impact
+======
+
+If this feature is needed, the ``compatibility6`` extension must be loaded to keep compatibility
+with older versions after upgrading from ``TYPO3 CMS 6.2``. If the extension is not loaded,
+flex form fields can no longer be localized on flex data level.
+
+
+Affected Installations
+======================
+
+All multi language installations that use flex form with meta field ``langDisable`` not set to 1
+in their data structure definition and that make active use of the flex localization feature.
+This is the case if records with flex form fields show flex forms multiple times with different
+language flags.
+
+
+Migration
+=========
+
+Load extension ``compatibily6`` for a compatibility layer in ``TYPO3 CMS 7``, or migrate affected
+features to use the record based localization feature. The flex field based language handling
+will most likely vanish with ``TYPO3 CMS 8`` altogether. In case the feature is needed for a
+longer time the code from ``compatibility6`` could be used as a kick start for an implementation
+within an own extension.
+
+In case ``compatibility6`` is loaded, some core content elements may start showing flex field
+language overlays since the ``langDisable`` meta definition has been removed from their data
+structure XML. This can be suppressed with this ``PageTS config`` snippet:
+
+.. code-block:: typoscript
+
+	TCEFORM.tt_content.pi_flexform.table.langDisable = 1
+	TCEFORM.tt_content.pi_flexform.login.langDisable = 1
+	TCEFORM.tt_content.pi_flexform.media.langDisable = 1
diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/FlexForms/tt_content_flexform.xml b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/FlexForms/tt_content_flexform.xml
index c3c93da6be2d..08bf9f81f058 100644
--- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/FlexForms/tt_content_flexform.xml
+++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/FlexForms/tt_content_flexform.xml
@@ -1,7 +1,4 @@
 <T3DataStructure>
-	<meta>
-		<langDisable>1</langDisable>
-	</meta>
 	<ROOT>
 		<type>array</type>
 		<el>
@@ -31,4 +28,4 @@
 			</hotels>
 		</el>
 	</ROOT>
-</T3DataStructure>
\ No newline at end of file
+</T3DataStructure>
diff --git a/typo3/sysext/css_styled_content/flexform_ds.xml b/typo3/sysext/css_styled_content/flexform_ds.xml
index 39245d2216ee..7e8d74181b7a 100644
--- a/typo3/sysext/css_styled_content/flexform_ds.xml
+++ b/typo3/sysext/css_styled_content/flexform_ds.xml
@@ -1,7 +1,4 @@
 <T3DataStructure>
-	<meta>
-		<langDisable>1</langDisable>
-	</meta>
 	<sheets>
 		<sDEF>
 			<ROOT>
diff --git a/typo3/sysext/felogin/Configuration/FlexForms/Login.xml b/typo3/sysext/felogin/Configuration/FlexForms/Login.xml
index 711341899191..ba0a543f191a 100644
--- a/typo3/sysext/felogin/Configuration/FlexForms/Login.xml
+++ b/typo3/sysext/felogin/Configuration/FlexForms/Login.xml
@@ -1,7 +1,4 @@
 <T3DataStructure>
-	<meta>
-		<langDisable>1</langDisable>
-	</meta>
 	<sheets>
 		<sDEF>
 			<ROOT>
diff --git a/typo3/sysext/impexp/Tests/Functional/Fixtures/Extensions/impexp_group_files/Configuration/TCA/tx_impexpgroupfiles_item.php b/typo3/sysext/impexp/Tests/Functional/Fixtures/Extensions/impexp_group_files/Configuration/TCA/tx_impexpgroupfiles_item.php
index 48fd32e27164..f409db99bfcb 100644
--- a/typo3/sysext/impexp/Tests/Functional/Fixtures/Extensions/impexp_group_files/Configuration/TCA/tx_impexpgroupfiles_item.php
+++ b/typo3/sysext/impexp/Tests/Functional/Fixtures/Extensions/impexp_group_files/Configuration/TCA/tx_impexpgroupfiles_item.php
@@ -131,9 +131,6 @@ return array(
 				'type' => 'flex',
 				'ds' => array(
 					'default' => '<T3DataStructure>
-							<meta>
-								<langDisable>1</langDisable>
-							</meta>
 							<sheets>
 								<sDEF>
 									<ROOT>
diff --git a/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php b/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php
index 29260e9fe9b4..55be768292ef 100644
--- a/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php
+++ b/typo3/sysext/install/Classes/Service/SilentConfigurationUpgradeService.php
@@ -98,6 +98,8 @@ class SilentConfigurationUpgradeService {
 		'BE/diff_path',
 		// #69930
 		'SYS/serverTimeZone',
+		// #70138
+		'BE/flexFormXMLincludeDiffBase',
 	);
 
 	/**
diff --git a/typo3/sysext/mediace/Configuration/FlexForms/media.xml b/typo3/sysext/mediace/Configuration/FlexForms/media.xml
index 719c160f2776..06c7c8cd5885 100644
--- a/typo3/sysext/mediace/Configuration/FlexForms/media.xml
+++ b/typo3/sysext/mediace/Configuration/FlexForms/media.xml
@@ -1,8 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <T3DataStructure>
-	<meta>
-		<langDisable>1</langDisable>
-	</meta>
 	<sheets>
 		<sGeneral>
 			<ROOT>
-- 
GitLab