How a wrong TCA configuration broke localization after updating to TYPO3 13.4
The initial problem
I have been doing a lot of TYPO3 major updates lately, and for one of the projects, a colleague of mine reported months later a strange problem with localization, which most likely is related to the update to TYPO3 13.4. The affected TYPO3 website contains a site which has two languages. The default language is german and the other language is English. The problem showed up when the user translated a record to english and some fields could not be translated anymore. Every time the user tried to save the translated record, the given translation for some fields was not saved, but the value of the original language was used.
Analysis and solution
To me this quickly sounded like a bug somewhere in the TCA of the affected table. So we started looking for possible misconfigurations in the TCA related to the localization, but everything was fine. Since the record was used in an TYPO3 inline field, we also started to look for possible misconfigurations in that direction but with no success. Finally, we looked at the TCA configuration for each field and found the following:
'title' => [
'exclude' => true,
'label' => 'LLL:EXT:sitepackage/Resources/Private/Language/locallang_tca.xlf:foo_table.title',
'config' => [
'type' => 'input',
'size' => 50,
'required' => true,
],
'behaviour' => [
'mode' => 'select',
'allowLanguageSynchronization' => true,
],
],
The behaviour configuration for the field title is placed wrong, because it should be placed under config.
Additionally, it contains the mode configuration, which is wrong too. After removing the behaviour configuration
array, the problem was solved and the translations for affected fields were saved correctly again.
The wrong configuration has been there for a long time, and the problem first appeared after the update to TYPO3 13.4. The main question for me was: Why did the problem appear after the update and why can a wrong TCA configuration cause the described behavior?
In-depth analysis
The reason for this behavior lies deep in TYPO3s DataHandler and DataMapProcessor. When a record is saved in
the backend, the DataHandler::process_datamap() function is called. This function calls the
DataMapProcessor::process() function to process the submitted datamap and to sanitize/enrich the datamap with
dependencies and localization states. The last part is interesting here, because it ensures that the
allowLanguageSynchronization feature for fields is working correctly. The default behavior for
allowLanguageSynchronization is to use the value of the original record as shown on the screenshot below.

In this particular case, the sanitation in DataMapProcessor::process() resulted in the submitted field value for
the title field being removed from the datamap. So somehow, the wrong TCA configuration for the field was
taken into account when it comes to translation handling.
After some debugging with xdebug and with the help of some AI prompts, I found the culprit in the TCA schema.
The reason why the wrong behaviour configuration suddenly took effect after the update to TYPO3 13.4
lies in the streamlineFieldConfiguration() function of FieldTypeFactory. The function removes the
config array from the field configuration and merges its contents into the top-level field array.
Before this schema processing was introduced in TYPO3 v13, the misplaced behaviour key at the top
level was silently ignored. After the update, once config is flattened into the top level, the
misplaced behaviour including allowLanguageSynchronization: true is now present in the merged
result and picked up by DataMapProcessor when deciding how to handle field values during translation
saving.
Learnings
- Always place
allowLanguageSynchronizationinsideconfig, not at the top level of the field configuration. - A wrong TCA configuration can remain unnoticed for years if older TYPO3 versions silently ignored it
- When a localization problem appears after a TYPO3 major update, the TCA configuration of the affected table is a good first place to look, especially for fields using translation-related options.
