Bug #61543

Language Fallback fails when displaying records, which have translation for other languages but not the current language

Added by Andre Knieriem 11 months ago. Updated 18 days ago.

Status:Needs Feedback Start date:2014-09-11
Priority:Must have Due date:
Assigned To:Andre Knieriem % Done:

0%

Category:- Spent time: -
Target version:-
TYPO3 Version:6.2 Is Regression:No
PHP Version: Sprint Focus:
Complexity:

Description

We are building on an extension with extbase and found something special:

If you have for example 3 Languages (en = 0, de =1, fr = 2) and

you create 4 Records in english and nothing else
- > all 4 records are showing up in all 3 languages in english

If you create translation for records in fr you then:
- > all 4 records showing in english => right
- > all 4 records showing in french => right
- > none record showing in german => wrong!

After some debugging we found out that addSysLanguageStatement in file:
/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php

makes the error.

if ($mode === 'strict') {
    $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=-1' .
        ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' = ' . (int)$querySettings->getLanguageUid() .
        ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '=0' .
        ') OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
        ' AND ' . $tableName . '.uid IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
        ' FROM ' . $tableName .
        ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
        ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=' . (int)$querySettings->getLanguageUid() ;
} else {
    $additionalWhereClause .= ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
        ' AND ' . $tableName . '.uid NOT IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
        ' FROM ' . $tableName .
        ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .    

' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '>0';

 }

The marked line is excluding uid's for fallback, if any translation for the record is found, but it has to remove only records that are in the current language.
The line should be deleted or extended.

So if you are in german (sys_language_uid = 1 in my example) it should be:
' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=1';


Related issues

related to Core - Bug #62155: IRRE at localized records not working properly with Extba... Rejected 2014-10-10

History

#1 Updated by Andre Knieriem 11 months ago

You can fix this bug with an XClass like so:

Add this to your ext_localconf.php

$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser'] = array(
    'className' => 'Tx_MyExt_XClass_Typo3DbQueryParser'
);

Add Typo3DbQueryParser.php with the following content to /Classes/XClasses/

<?php

class Tx_MyExt_XClass_Typo3DbQueryParser extends \TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser
{

    /**
     * Builds the language field statement
     *
     * @param string $tableName The database table name
     * @param array &$sql The query parts
     * @param QuerySettingsInterface $querySettings The TYPO3 CMS specific query settings
     * @return void
     */
    protected function addSysLanguageStatement($tableName, array &$sql, $querySettings) {

        if (is_array($GLOBALS['TCA'][$tableName]['ctrl'])) {
            if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField'])) {
                // Select all entries for the current language
                $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' IN (' . (int)$querySettings->getLanguageUid() . ',-1)';
                // If any language is set -> get those entries which are not translated yet
                // They will be removed by t3lib_page::getRecordOverlay if not matching overlay mode
                if (isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'])
                    && $querySettings->getLanguageUid() > 0
                ) {

                    $mode = $querySettings->getLanguageMode();
                    if ($mode === 'strict') {
                        $additionalWhereClause = $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=-1' .
                            ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . ' = ' . (int)$querySettings->getLanguageUid() .
                            ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '=0' .
                            ') OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
                            ' AND ' . $tableName . '.uid IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
                            ' FROM ' . $tableName .
                            ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
                            ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=' . (int)$querySettings->getLanguageUid() ;
                    } else {
                        $additionalWhereClause .= ' OR (' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '=0' .
                            ' AND ' . $tableName . '.uid NOT IN (SELECT ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] .
                            ' FROM ' . $tableName .
                            ' WHERE ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'] . '>0' .
                            ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '='.(int)$querySettings->getLanguageUid();
                            //see https://forge.typo3.org/issues/61543
                            //' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] . '>0';
                    }

                    // Add delete clause to ensure all entries are loaded
                    if (isset($GLOBALS['TCA'][$tableName]['ctrl']['delete'])) {
                        $additionalWhereClause .= ' AND ' . $tableName . '.' . $GLOBALS['TCA'][$tableName]['ctrl']['delete'] . '=0';
                    }
                    $additionalWhereClause .= '))';
                }
                $sql['additionalWhereClause'][] = '(' . $additionalWhereClause . ')';
            }
        }
    }
}


Remember to rename the Classnames to your Extkeys!

#2 Updated by Riccardo De Contardi 18 days ago

  • Status changed from New to Needs Feedback
  • Assigned To set to Andre Knieriem

Hi Andre,

is there work left to do on this topic? Could this be closed? Thank you!

#3 Updated by Andre Knieriem 18 days ago

Riccardo De Contardi wrote:

is there work left to do on this topic? Could this be closed? Thank you!

Hi Riccardo, the problem is fixed. You can see it in the file i named above.

Also available in: Atom PDF