[!!!][TASK] Remove deprecated code from TableController
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Documentation / Changelog / 9.5 / Important-82363-MakeExtBaseTranslationHandlingConsistentWithTyposcript.rst
1 .. include:: ../../Includes.txt
2
3 ================================================================================
4 Important: #82363 - Make Extbase translation handling consistent with TypoScript
5 ================================================================================
6
7 See :issue:`82363`
8
9 Description
10 ===========
11
12 Extbase now renders the translated records in the same way TypoScript rendering does.
13 The new behaviour is controlled by the Extbase feature switch :typoscript:`consistentTranslationOverlayHandling`.
14
15 .. code-block:: typoscript
16
17 config.tx_extbase.features.consistentTranslationOverlayHandling = 1
18
19 The new behaviour is default in TYPO3 v9. The feature switch will be removed in TYPO3 v10, so there will be just
20 one way of fetching records.
21 You can override the setting using normal TypoScript.
22
23
24 Impact
25 ======
26
27 Users relying on the old behaviour can disable the feature switch.
28
29 The change modifies how Extbase interprets the TypoScript settings
30 :ts:`config.sys_language_mode` and :ts:`config.sys_language_overlay` and the
31 :php:`Typo3QuerySettings` properties :php:`languageOverlayMode` and :php:`languageMode`.
32
33 Changes in the rendering:
34
35 1) Setting :php:`Typo3QuerySettings->languageMode` does **not** influence how Extbase queries records anymore.
36 The corresponding TypoScript setting :ts:`config.sys_language_mode` is used by the core
37 to decide what to do when a page is not translated to the given language (display 404, or try page with different language).
38 Users who used to set :php:`Typo3QuerySettings->languageMode` to `strict` should use
39 :php:`Typo3QuerySettings->setLanguageOverlayMode('hideNonTranslated')` to get translated records only.
40
41 The old behavior was confusing, because `languageMode` had different meaning and accepted different
42 values in TS context and in Extbase context.
43
44 2) Setting :php:`Typo3QuerySettings->languageOverlayMode` to :php:`true` makes Extbase fetch records
45 from default language and overlay them with translated values. So e.g. when a record is hidden in
46 the default language, it will not be shown. Also records without translation parents will not be shown.
47 For relations, Extbase reads relations from a translated record (so it’s not possible to inherit
48 a field value from translation source) and then passes the related records through :php:`$pageRepository->getRecordOverlay()`.
49 So e.g. when you have a translated `tt_content` with FAL relation, Extbase will show only those
50 `sys_file_reference` records which are connected to the translated record (not caring whether some of
51 these files have `l10n_parent` set).
52
53 Previously :php:`Typo3QuerySettings->languageOverlayMode` had no effect.
54 Extbase always performed an overlay process on the result set.
55
56 3) Setting :php:`Typo3QuerySettings->languageOverlayMode` to :php:`false` makes Extbase fetch aggregate
57 root records from a given language only. Extbase will follow relations (child records) as they are,
58 without checking their `sys_language_uid` fields, and then it will pass these records through
59 :php:`$pageRepository->getRecordOverlay()`.
60 This way the aggregate root record's sorting and visibility doesn't depend on default language records.
61 Moreover, the relations of a record, which are often stored using default language uids,
62 are translated in the final result set (so overlay happens).
63
64 For example:
65 Given a translated `tt_content` having relation to 2 categories (in the mm table translated
66 tt_content record is connected to category uid in default language), and one of the categories is translated.
67 Extbase will return a `tt_content` model with both categories.
68 If you want to have just translated category shown, remove the relation in the translated `tt_content`
69 record in the TYPO3 Backend.
70
71 Note that by default :php:`Typo3QuerySettings` uses the global TypoScript configuration like
72 :ts:`config.sys_language_overlay` and :php:`$GLOBALS['TSFE']->sys_language_content`
73 (calculated based on :ts:`config.sys_language_uid` and :ts:`config.sys_language_mode`).
74 So you need to change :php:`Typo3QuerySettings` manually only if your Extbase code should
75 behave different than other `tt_content` rendering.
76
77 Setting :php:`setLanguageOverlayMode()` on a query influences **only** fetching of the aggregate root. Relations are always
78 fetched with :php:`setLanguageOverlayMode(true)`.
79
80 When querying data in translated language, and having :php:`setLanguageOverlayMode(true)`, the relations
81 (child objects) are overlaid even if aggregate root is not translated.
82 See :php:`QueryLocalizedDataTest->queryFirst5Posts()`.
83
84 Following examples show how to query data in Extbase in different scenarios, independent of the global TS settings:
85
86 1) Fetch records from the language uid=1 only, with no overlays.
87 Previously (:ts:`consistentTranslationOverlayHandling = 0`):
88
89 It was not possible.
90
91
92 Now (:ts:`consistentTranslationOverlayHandling = 1`):
93
94 ::
95
96 $querySettings = $query->getQuerySettings();
97 $querySettings->setLanguageUid(1);
98 $querySettings->setLanguageOverlayMode(false);
99
100 2) Fetch records from the language uid=1, with overlay, but hide non-translated records
101 Previously (:ts:`consistentTranslationOverlayHandling = 0`):
102
103 ::
104
105 $querySettings = $query->getQuerySettings();
106 $querySettings->setLanguageUid(1);
107 $querySettings->setLanguageMode('strict');
108
109 Now (:ts:`consistentTranslationOverlayHandling = 1`):
110
111 ::
112
113 $querySettings = $query->getQuerySettings();
114 $querySettings->setLanguageUid(1);
115 $querySettings->setLanguageOverlayMode('hideNonTranslated');
116
117
118 +------------------------+-------------------------------------------------------------------------------------------------+----------------------------------------------+------------------------------+
119 | QuerySettings property | old behaviour | new behaviour | default value (TSFE|Extbase) |
120 +========================+=================================================================================================+==============================================+==============================+
121 | languageUid | | same | 0 |
122 +------------------------+-------------------------------------------------------------------------------------------------+----------------------------------------------+------------------------------+
123 | respectSysLanguage | | same | `true` |
124 +------------------------+-------------------------------------------------------------------------------------------------+----------------------------------------------+------------------------------+
125 | languageOverlayMode | not used | values: `true`, `false`, `hideNonTranslated` | 0 | `true` |
126 | | | | |
127 +------------------------+-------------------------------------------------------------------------------------------------+----------------------------------------------+------------------------------+
128 | languageMode | documented values: `null`, `content_fallback`, `strict` or `ignore`. | not used | `null` |
129 | | Only `strict` was evaluated. Setting `LanguageMode` to `strict` | | |
130 | | caused passing `hideNonTranslated` param to `getRecordOverlay` in :php:`Typo3DbBackend` | | |
131 | | and changing the query to work similar to TypoScript `sys_language_overlay = hideNonTranslated` | | |
132 +------------------------+-------------------------------------------------------------------------------------------------+----------------------------------------------+------------------------------+
133
134
135 Identifiers
136 -----------
137
138 Domain models have a main identifier `uid` and two additional properties `_localizedUid` and `_versionedUid`.
139 Depending on whether the `languageOverlayMode` mode is enabled (`true` or `'hideNonTranslated'`) or disabled (`false`),
140 the identifier contains different values.
141 When `languageOverlayMode` is enabled then `uid` property contains `uid` value of the default language record,
142 the `uid` of the translated record is kept in the `_localizedUid`.
143
144 +----------------------------------------------------------+-------------------------+---------------------------+
145 | Context | Record in language 0 | Translated record |
146 +==========================================================+=========================+===========================+
147 | Database | uid:2 | uid:11, l10n_parent:2 |
148 +----------------------------------------------------------+-------------------------+---------------------------+
149 | Domain Object values with `languageOverlayMode` enabled | uid:2, _localizedUid:2 | uid:2, _localizedUid:11 |
150 +----------------------------------------------------------+-------------------------+---------------------------+
151 | Domain Object values with `languageOverlayMode` disabled | uid:2, _localizedUid:2 | uid:11, _localizedUid:11 |
152 +----------------------------------------------------------+-------------------------+---------------------------+
153
154 See tests in :file:`extbase/Tests/Functional/Persistence/QueryLocalizedDataTest.php`.
155
156 The :php:`$repository->findByUid()` (or :php:`$persistenceManager->getObjectByIdentifier()`) method takes current
157 rendering language into account (e.g. L=1). It does not take `defaultQuerySetting` set on the repository into account.
158 This method always performs an overlay.
159 Values in braces show previous behaviour (disabled flag) if different than current.
160
161 The bottom line is that with the feature flag on, you can now use :php:`findByUid()` using translated record uid to get
162 translated content independently from language set in global context.
163
164 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
165 | | | L=0 | L=1 |
166 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
167 | repository method | property | Overlay | No overlay | Overlay | No overlay |
168 +===================+================+======================+======================+======================+======================+
169 | findByUid(2) | title | Post 2 | Post 2 | Post 2 - DK | Post 2 - DK |
170 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
171 | | uid | 2 | 2 | 2 | 2 |
172 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
173 | | _localizedUid | 2 | 2 | 11 | 11 |
174 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
175 | findByUid(11) | title | Post 2 - DK (Post 2) | Post 2 - DK (Post 2) | Post 2 - DK | Post 2 - DK |
176 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
177 | | uid | 2 | 2 | 2 | 2 |
178 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
179 | | _localizedUid | 11 (2) | 11 (2) | 11 | 11 |
180 +-------------------+----------------+----------------------+----------------------+----------------------+----------------------+
181
182 .. note::
183
184 Note that :php:`$repository->findByUid()` internally sets :php:`respectSysLanguage(false)` so it behaves differently
185 than a regular query by an `uid` like :php:`$query->matching($query->equals('uid', 11));`
186 The regular query will return :php:`null` if passed `uid` doesn't match
187 the language set in the :php:`$querySettings->setLanguageUid()` method.
188
189 Filtering & sorting
190 -------------------
191
192 When filtering by aggregate root property like `Post->title`,
193 both filtering and sorting takes translated values into account and you will get correct results, also with pagination.
194
195 When filtering or ordering by child object property, then Extbase does a left join between aggregate root
196 table and child record table.
197 Then the filter is applied as where clause. This means that filtering or ordering by child record property
198 only takes values from child records which uids are stored in db (in most cases its default language record).
199 See :php:`TranslationTest::fetchingTranslatedPostByBlogTitle()`
200
201 This limitation also applies to Extbase with feature flag being disabled.
202
203 Summary of the important code changes
204 =====================================
205
206 1) :php:`DataMapper` gets a :php:`Query` as a constructor parameter. This allows to use aggregate root :php:`QuerySettings` (language)
207 when fetching child records/relations. Later, in a separate patch we can pass other settings too e.g. :php:`setIgnoreEnableFields`
208 to fix issue around this setting. See :php:`DataMapper->getPreparedQuery` method.
209 2) :php:`DataMapper` is passed to :php:`LazyLoadingProxy` and :php:`LazyObjectStorage`, so the settings don't get lost when fetching data lazily.
210 3) :php:`Query` object gets a new property `parentQuery` which is useful to detect whether we're fetching aggregate root or child object.
211 4) Extbase model for :php:`FileReference` uses `_localizedUid` for fetching `OriginalResource`
212 5) :php:`DataMapper` forces child records to be fetched using :php:`setLanguageOverlayMode(true)`.
213 6) When getRespectSysLanguage is set, :php:`DataMapper` uses aggregate root language to overlay child records to correct language.
214 7) The `where` clause used for finding translated records in overlay mode (`true`, `hideNonTranslated`) has been fixed.
215 It filters out the non translated records on db side in case `hideNonTranslated` is set.
216 It allows for filtering and sorting by translated values. See :php:`Typo3DbQueryParser->getLanguageStatement()`
217
218
219 Most important known issues (ones this patch doesn't solve)
220 ===========================================================
221
222 - Persistence session uses the same key for default language record and the translation - https://forge.typo3.org/issues/59992
223 - Extbase allows to fetch deleted/hidden records - https://forge.typo3.org/issues/86307
224
225
226 For more information about rendering please refer to the TypoScript reference_.
227
228 .. _reference: https://docs.typo3.org/typo3cms/TyposcriptReference/Setup/Config/Index.html?highlight=sys_language_mode#sys-language-overlay
229
230 .. index:: Database, TCA, TypoScript, ext:extbase