Known issues
Translation options not shown
When API key is not set, deepltranslate_core disables all functions. Go to Settings and fix it. Clear cache after this.
TYPO3 Core patch may be required (l10n_source)
Localizing a record whose table declares a translation source field
(l10n_source) - for example content elements built with MASK - can create
a duplicate translation in the same language. This is the root cause of the
duplicated translations reported for web-vision/deepltranslate-auto-renew in
#42.
The defect is in the TYPO3 Core, not in this extension:
BackendUtility::getRecordLocalization() matches existing translations by
l10n_source when the table defines one and does not fall back to
l10n_parent. A valid translation created without populating l10n_source
(the usual result of a plain DataHandler datamap, an importer, a migration or
MASK) is not found, so DataHandler::localize() creates a second one.
The fix is upstream: forge #110281, Gerrit 94915 (13.4) and released with TYPO3 v13.4.34. This extension requires at least that version on the TYPO3 v13 side, so nothing has to be done on TYPO3 v13.
TYPO3 v12.4 has reached ELTS and never receives the fix. Instances on TYPO3 v12.4 have to apply the patch themselves.
No Composer patch is declared any more
Earlier releases declared the patch in the extra.patches section of the
composer.json of this extension. That declaration used the object form with
a source and a version key, which only
vaimo/composer-patches
understands. Patch declarations are collected from installed dependencies as
well, so projects using
cweagans/composer-patches
aborted their Composer run with an "Array to string conversion" error (1.7.3) or
a type error in ResolverBase (2.0.0). See
deepltranslate-core#646.
The extension therefore no longer declares or applies any Composer patch.
The patch file below Documentation/CorePatches/ stays in the repository as
documentation.
Applying the patch in a project
Copy Documentation/CorePatches/typo3-cms-backend-110281-v12-v13.patch from
web-vision/deepltranslate-core
into the project - for example into its patches/ directory - and declare it
for typo3/cms-backend.
With cweagans/composer-patches the patch is declared as a plain path or URL
string:
{
"extra": {
"patches": {
"typo3/cms-backend": {
"TYPO3 #110281 l10n_source": "patches/typo3-cms-backend-110281-v12-v13.patch"
}
}
}
}
vaimo/composer-patches additionally understands the object form, which can
scope a patch to the affected TYPO3 versions:
{
"extra": {
"patches": {
"typo3/cms-backend": {
"TYPO3 #110281 l10n_source": {
"source": "patches/typo3-cms-backend-110281-v12-v13.patch",
"version": ">=12.4.0 <13.0.0"
}
}
}
}
}
Patches the project applies to typo3/cms-backend itself may need adoption:
they have to apply on top of the changes shown below, otherwise patching fails
and aborts the Composer run. The same is true for patches provided by other
extensions for the same file.
See the general TYPO3 documentation on applying Composer patches for project-specific setup details. The patch shipped by this extension:
diff --git a/Classes/Utility/BackendUtility.php b/Classes/Utility/BackendUtility.php
index 893f781..f442596 100644
--- a/Classes/Utility/BackendUtility.php
+++ b/Classes/Utility/BackendUtility.php
@@ -27,6 +27,7 @@
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Platform\PlatformInformation;
+use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\QueryHelper;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
@@ -293,10 +294,7 @@
$queryBuilder->select('*')
->from($table)
->where(
- $queryBuilder->expr()->eq(
- $tcaCtrl['translationSource'] ?? $tcaCtrl['transOrigPointerField'],
- $queryBuilder->createNamedParameter($uid, Connection::PARAM_INT)
- ),
+ self::createTranslationParentConstraint($queryBuilder, $tcaCtrl, (int)$uid),
$queryBuilder->expr()->eq(
$tcaCtrl['languageField'],
$queryBuilder->createNamedParameter((int)$language, Connection::PARAM_INT)
@@ -314,6 +312,44 @@
return $recordLocalization;
}
+ /**
+ * Constraint matching all translations of the given record.
+ *
+ * `translationSource` (l10n_source) is preferred, since it is the more precise information for
+ * translation chains. It is however not maintained by all writes - a DataHandler datamap which
+ * creates a translation by only setting the language field and the transOrigPointerField leaves
+ * it empty - so such records are matched by their transOrigPointerField (l10n_parent) instead.
+ * Without that, valid translations would be invisible for callers like
+ * `DataHandler::localize()`, which uses this lookup to prevent duplicate translations.
+ *
+ * @param array $tcaCtrl The `ctrl` section of the table
+ */
+ protected static function createTranslationParentConstraint(
+ QueryBuilder $queryBuilder,
+ array $tcaCtrl,
+ int $uid
+ ): CompositeExpression|string {
+ $uidParameter = $queryBuilder->createNamedParameter($uid, Connection::PARAM_INT);
+ $translationOriginPointerConstraint = $queryBuilder->expr()->eq(
+ $tcaCtrl['transOrigPointerField'],
+ $uidParameter
+ );
+ if (!isset($tcaCtrl['translationSource'])) {
+ return $translationOriginPointerConstraint;
+ }
+
+ return $queryBuilder->expr()->or(
+ $queryBuilder->expr()->eq($tcaCtrl['translationSource'], $uidParameter),
+ $queryBuilder->expr()->and(
+ $queryBuilder->expr()->eq(
+ $tcaCtrl['translationSource'],
+ $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)
+ ),
+ $translationOriginPointerConstraint
+ )
+ );
+ }
+
/*******************************************
*
* Page tree, TCA related