Translations are created on the wrong page if translations were moved previously (severe)
(Occurs in TYPO3 8.7.17 and TYPO3 8.7.19 both PHP 7.0.32, I expect the bug to also occur in 9.5 LTS but have not yet tested that.)
The bug is demonstrated in translation-on-wrong-page.mov. The following steps are an even easier way to recreate the issue.
1. Have 2 pages that each are translated to at least one non-default language.
2. Create a content element on page 1 (called element 1) and translate it (transalation 1).
3. Open translation 1 and set "Transl.Orig" in the "Language" tab from "element 1" to empty.
4. Copy or move translation 1 to page 2.
5. Create a second content element on page 1 (element 2) (and delete translation 1 if you did copy and not move in step 4).
6. Use the 4-step localization wizard to translate page 1 (element 1 and 2 are expected to be translated).
7. See that only element 1 has been correctly translated. The translation of element 2 was created on page 2.
8. If you translate element 2 from within the element (language select NEW) then another "translation" will be created on page 2 which does not really count as translation because it is not on the same page.
9. You can repeat step 8 as often as you want by switching back the to the default language and re-translating element 2.
Note that so far I could only recreate the bug by changing the l18n_parent (Transl.Orig) manually at least once. It could be very well possible that this also occurs even if you never change that field manually (see explanation in background).
The reason that the wrong pid is chosen for the translation seems to be that for at least one content element that is being translation (called element A) there is an element on a different page that has element A's uid as l10n_source (called element B). This means that element B was at some page a translation or a copy of translation of element A but was moved or copied to a different pid. As long as there is at least one such element B for any of the elements to be translated then the translation of this element will be created on the page of the element's respective element B.
This means that if you translate a page with the 4-step localization wizard there can be translations created on several different pages than the one you are running the localization wizard on.
Note that this can usually fixed by deleting all the element Bs. But first of all you can only know on which site they are on by looking at the pid if the newly created translation (as they are on the same page). If the element B is inside a gridelement then you may not be able to delete it normally because it is not shown in the site modul (because its container was deleted).
With this SQL you can see if your system is affected:
select t1.uid, t1.pid, t1.l10n_source, t2.uid, t2.pid from tt_content as t1 join tt_content as t2 on t1.l10n_source = t2.uid where t1.pid <> t2.pid and t1.deleted = 0;
With this SQL you can quickfix the problem. After that you can re-translate the affected page and the translations will be created on the same page as expected.
UPDATE tt_content JOIN (select t1.uid from tt_content as t1 join tt_content as t2 on t1.l10n_source = t2.uid where t1.pid <> t2.pid and t1.deleted = 0 ) t3 ON tt_content.uid = t3.uid set tt_content.l10n_source = 0;
I don't know enough about the use of l10n_source to make a clear proposition. I know that it is a rather new field. I don't know why the 4-step localization wizard should regard it (what for?). l10n_source does not say whether or not there is already a valid translation fo an element (and therefore no translation must be made). If there is no element with l18n_parent = [uid of the element to translated] and deleted = 0 and pid = [pid of the element to be translated] then a translation should be made, obviously with the same pid. It seems that the affected element itself is translated correctly but the next element gets the wrong pid. Why the pid of any translated element is taken from some random element that references the element to be translated with l10n_source and not from the element to be translated itself is completely beyond me.
Of course you could prevent the state (that an element with l10n_source of an other element is not on the same page) to occur at all but that is probably much harder. If this is the way to go then l10n_source must be set 0 when moving/copying elements but I don't think that is the right way.