Important: Strict language fallback for selected profiles
Description
When profiles are selected explicitly (by uid) for a list plugin
(
academicpersons_ /
academicpersons_ with the
FlexForm "selected profiles" option), a site language configured with
fallback did not hide profiles that are not translated into
the requested language. Such profiles were rendered in their default language
instead of being removed, unless the plugin option "fallback for non
translated" was enabled on purpose.
This is not an
EXT: bug. The extension already
resolves the correct language overlay type from the site configuration and only
relies on Extbase persistence to apply it. The behaviour is caused by a
long-standing Extbase regression that ignored the resolved language overlay type
and always overlaid single records with
OVERLAYS_, so untranslated
records were kept.
Core references (issue and both patches):
- Forge issue #88886 — "DataMapper: Consider languageOverlayMode hideNonTranslated ..."
- Gerrit change 66694 — "[BUGFIX] Respect language overlay type in Extbase" (TYPO3 main line)
- Gerrit change 94935 — the TYPO3 14.3 backport (same Change-Id)
The fix is released with TYPO3 v14.3.6 and newer (and on the TYPO3 main development line). It is not part of TYPO3 v13 and, being a behavioural change, is not backported to the v13.4 LTS.
Impact
On TYPO3 v14.3.6 and newer the behaviour is correct out of the box:
untranslated selected profiles are removed under
fallback. No
configuration or code change is required in
EXT:.
On TYPO3 v13.4 (and on TYPO3 v14.3.0 - v14.3.5, before the fix shipped)
the affected Extbase code still overlays with
OVERLAYS_, so
untranslated selected profiles keep being shown in their default language when the
site language uses
fallback and the plugin fallback option is
not enabled.
The two functional tests covering this behaviour
(
Academic and
Academic,
test
...) are therefore
skipped on TYPO3 below v14.3.6 and run only where the core fix is present.
Affected Installations
Installations that use selected profiles in a list plugin with a site language
configured as
fallback and expect untranslated profiles to be
hidden, running on TYPO3 v13.4 or TYPO3 v14.3.0 - v14.3.5.
Solution
Upgrade to TYPO3 v14.3.6 or newer, which contains the core fix.
If the correct behaviour is required before that, apply the core change as a
composer patch against
typo3/ until it is part of the installed
core version. Cleaned patches (narrowed to
typo3/, derived from
Gerrit changes 66694 / 94935) are shipped with this extension:
TYPO3 v13.4 patch
Documentation/
diff -ruN a/Classes/Persistence/Generic/Backend.php b/Classes/Persistence/Generic/Backend.php
--- a/Classes/Persistence/Generic/Backend.php
+++ b/Classes/Persistence/Generic/Backend.php
@@ -148,11 +148,14 @@
// This allows to fetch IDs for languages for default language AND language IDs
// This is especially important when using the PropertyMapper of the Extbase MVC part to get
// an object of the translated version of the incoming ID of a record.
+ // "Free" mode (OVERLAYS_OFF) is mapped to OVERLAYS_MIXED - overlays need to be enabled for the
+ // identity lookup, but hiding untranslated records is not a configured intent in free mode.
+ // This is consistent with the same handling for related objects in DataMapper->getPreparedQuery().
$languageAspect = $query->getQuerySettings()->getLanguageAspect();
$languageAspect = new LanguageAspect(
$languageAspect->getId(),
$languageAspect->getContentId(),
- $languageAspect->getOverlayType() === LanguageAspect::OVERLAYS_OFF ? LanguageAspect::OVERLAYS_ON_WITH_FLOATING : $languageAspect->getOverlayType(),
+ $languageAspect->getOverlayType() === LanguageAspect::OVERLAYS_OFF ? LanguageAspect::OVERLAYS_MIXED : $languageAspect->getOverlayType(),
$languageAspect->getFallbackChain()
);
$query->getQuerySettings()->setLanguageAspect($languageAspect);
diff -ruN a/Classes/Persistence/Generic/Storage/Typo3DbBackend.php b/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
--- a/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
+++ b/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
@@ -580,9 +580,16 @@
$row['uid'] = $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']];
$row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']] = 0;
}
- // Currently this needs to return the default record (OVERLAYS_MIXED) if no translation is found
- //however this is a hack and should actually use the overlay functionality as given in the original LanguageAspect.
- $customLanguageAspect = new LanguageAspect($languageUid, $languageUid, LanguageAspect::OVERLAYS_MIXED, $languageAspect->getFallbackChain());
+ // The overlay type (and fallback chain) of the language aspect is respected, so translation
+ // behavior is consistent with the regular page / content rendering. The content language
+ // however may have been adjusted above to the language of the actually fetched record
+ // (see Note #1 and the respectSysLanguage handling), so a custom aspect is passed here.
+ $customLanguageAspect = new LanguageAspect(
+ $languageAspect->getId(),
+ $languageUid,
+ $languageAspect->getOverlayType(),
+ $languageAspect->getFallbackChain()
+ );
$row = $pageRepository->getLanguageOverlay($tableName, $row, $customLanguageAspect);
}
} elseif (is_array($row)) {
TYPO3 v14.3 patch (v14.3.0 - v14.3.5)
Documentation/
--- a/Classes/Persistence/Generic/Backend.php
+++ b/Classes/Persistence/Generic/Backend.php
@@ -165,11 +165,14 @@
// This allows to fetch IDs for languages for default language AND language IDs
// This is especially important when using the PropertyMapper of the Extbase MVC part to get
// an object of the translated version of the incoming ID of a record.
+ // "Free" mode (OVERLAYS_OFF) is mapped to OVERLAYS_MIXED - overlays need to be enabled for the
+ // identity lookup, but hiding untranslated records is not a configured intent in free mode.
+ // This is consistent with the same handling for related objects in DataMapper->getPreparedQuery().
$languageAspect = $query->getQuerySettings()->getLanguageAspect();
$languageAspect = new LanguageAspect(
$languageAspect->getId(),
$languageAspect->getContentId(),
- $languageAspect->getOverlayType() === LanguageAspect::OVERLAYS_OFF ? LanguageAspect::OVERLAYS_ON_WITH_FLOATING : $languageAspect->getOverlayType(),
+ $languageAspect->getOverlayType() === LanguageAspect::OVERLAYS_OFF ? LanguageAspect::OVERLAYS_MIXED : $languageAspect->getOverlayType(),
$languageAspect->getFallbackChain()
);
--- a/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
+++ b/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
@@ -590,9 +590,16 @@
$row['uid'] = $row[$translationParentPointerField];
$row[$languageField] = 0;
}
- // Currently this needs to return the default record (OVERLAYS_MIXED) if no translation is found
- //however this is a hack and should actually use the overlay functionality as given in the original LanguageAspect.
- $customLanguageAspect = new LanguageAspect($languageUid, $languageUid, LanguageAspect::OVERLAYS_MIXED, $languageAspect->getFallbackChain());
+ // The overlay type (and fallback chain) of the language aspect is respected, so translation
+ // behavior is consistent with the regular page / content rendering. The content language
+ // however may have been adjusted above to the language of the actually fetched record
+ // (see Note #1 and the respectSysLanguage handling), so a custom aspect is passed here.
+ $customLanguageAspect = new LanguageAspect(
+ $languageAspect->getId(),
+ $languageUid,
+ $languageAspect->getOverlayType(),
+ $languageAspect->getFallbackChain()
+ );
$row = $pageRepository->getLanguageOverlay($tableName, $row, $customLanguageAspect);
}
} elseif (is_array($row)) {
Apply the matching patch with the composer plugin
cweagans/composer-patches
(see its README for installation and usage). Copy the patch into the project
(for example into a patches/ directory) and reference it:
{
"require": {
"cweagans/composer-patches": "^1.7"
},
"extra": {
"patches": {
"typo3/cms-extbase": {
"Respect language overlay type in Extbase (forge #88886, review 66694)": "patches/extbase-88886-respect-language-overlay-type-v13.patch"
}
}
}
}
Both patches touch only
typo3/
(Classes/ and
Classes/);
EXT:
itself needs no change.