TYPO3 typoscript if condition based on site language - typo3

My typo3 version is 11.5.10.
I have two footer images, one for German and one for English .
I want to render different image for different language.
I tried this way for German language.
[siteLanguage("locale") == "de_DE"]
50 = COA
50 {
wrap = <div class="footer__item col-sm-6 col-md-3 img-custom">|</div>
stdWrap {
typolink {
parameter = {$myconstant.footer-logo-link-4}
parameter.noTrimWrap = || _blank|
}
}
50 = IMAGE
50 {
file = user_uploads/german-footer.png
layoutKey = srcset
layout.srcset {
element = <img WIDTH###" SOURCECOLLECTION###" ###PARAMS### ###ALTPARAMS### ###SELFCLOSINGTAGSLASH###> }
}
}
[end]
And for English language.
[siteLanguage("locale") == "en_US"]
50 = COA
50 {
wrap = <div class="footer__item col-sm-6 col-md-3 img-custom">|</div>
stdWrap {
typolink {
parameter = {$myconstant.footer-logo-link-5}
parameter.noTrimWrap = || _blank|
}
}
50 = IMAGE
50 {
file = user_uploads/english-footer.png
layoutKey = srcset
layout.srcset {
element = <img WIDTH###" SOURCECOLLECTION###" ###PARAMS### ###ALTPARAMS### ###SELFCLOSINGTAGSLASH###> }
}
}
[end]
In both language FE i get English-footer.
I also tried Different function of siteLanguage like
siteLanguage("navigationTitle")
siteLanguage("locale")
siteLanguage("hreflang") etc..
What i am doing wrong ?
Thanks in advance!
I get the following error in Typoscript Object Browser
Errors and warnings
Warning : Line 5696: Object Name String, "[siteLanguage" contains invalid character "[". Must be alphanumeric or one of: "_:-/." Show details
Warning : Line 5718: Object Name String, "[END]" contains invalid character "[". Must be alphanumeric or one of: "_:-/." Show details
Warning : Line 5719: Object Name String, "[siteLanguage" contains invalid character "[". Must be alphanumeric or one of: "_:-/." Show details
Warning : Line 5741: Object Name String, "[END]" contains invalid character "[". Must be alphanumeric or one of: "_:-/." Show details

In general, you should avoid conditions whenever possible. Conditions are evil!
Conditions are checked for each and every page request - before any cached content is touched. extensive use of conditions will be a performance killer.
For more details, search for "typo3 condition performance"
Using TypoScript if
A better way would be using the if-function, which is cachable, in combination with getText siteLanguage.
page.10 = TEXT
page.10.data = siteLanguage:languageId
page.10.stdWrap.wrap = <p>siteLanguage:languageId=|</p>
page.20 = IMAGE
page.20 {
if.value = 1
if.equals.data = siteLanguage:languageId
file = EXT:example/Resources/Public/typo3_package_de.png
}
page.30 = IMAGE
page.30 {
if.value = 0
if.equals.data = siteLanguage:languageId
file = EXT:example/Resources/Public/typo3_package_en.png
}

Related

Pass a variable to a content object containing a tx_news plugin

This is very similar to my question Counter for mask elements in a TYPO3 column
I need to pass a variable (in my case, the value of cObj:parentRecordNumber which is the counter for the current item in it's column) to the template.
In the main page template:
<f:cObject typoscriptObjectPath="lib.content.pageteasers" />
In typoscript:
lib.content {
pageteasers < styles.content.get
pageteasers {
select {
where = colPos=2
max = 8
}
// this passes the variable elementCounter to the fluid template of the rendered mask content element:
renderObj.mask_teaser {
variables {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
}
// this should pass the same value to a rendered tx_news plugin:
variables {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
// it doesn't. what about these trial & error:
renderObj.list < .variables
renderObj.plugin.tx_news < .variables
renderObj.list.20.news_pi1 < .variables
renderObj.news_pi1 < .variables
// none of these seem to work either
}
}
And then in the rendered CE template (News/List.html)
<f:debug title="" inline="1">{_all}</f:debug>
I don't manage to see the above variable in here. What is the correct way to pass the variable from TS to the news fluid template?
PS Another try was using the Good Old Register
pageteasers < styles.content.get
pageteasers {
select {
where = colPos=2
max = 8
}
append = LOAD_REGISTER
append {
elementCounter = TEXT
elementCounter.value = {cObj:parentRecordNumber}
elementCounter.insertData = 1
}
}
And in the template:
{v:variable.register.get(name: 'elementCounter')}
but that is NULL
Your try via register could work. But you have to care, where you are doing what...
Registers
LOAD_REGISTER is of type string/stdWrap and not a cObject per definition. If you wanna use content based on a cObject, you can declare this via the stdWrap-property (as shown in the examples):
1 = LOAD_REGISTER
1.param.cObject = TEXT
1.param.cObject.stdWrap.data = GP:the_id
So, in your case it should like:
elementCounter.cObject = TEXT
elementCounter.cObject.data = cObj:parentRecordNumber
Appending at the right place
You are trying to use append directly as a property of pageteasers (which is a copy of styles.content.get which is of type CONTENT.
CONTENT does not have an append-property. In addition, you would put the register in front of the entire content, not the individual content elements.
=> It's needed as part of the renderObj, so it's rendered per CE.
The renderObj of CONTENT is of type CASE, which also has no stdWrap-properties directly. But it has a property stdWrap with stdWrap-properties...
Conclusion
So, you can end up with this snippet:
lib.content {
pageteasers {
renderObj {
stdWrap {
append = LOAD_REGISTER
append {
elementCounter.cObject = TEXT
elementCounter.cObject.data = cObj:parentRecordNumber
}
}
}
}
}

How to escape variables in Typoscript setup?

I'm trying to wrap an image with additional HTML elements and parameters, using Typoscript in a Setup Template.
So far, I've managed to wrap elements with HTML, but I'd like to add some parameters as well. The problem occurs, when I try to escape variables in variables - I can't pass UID from one of the parameters.
Below is the sample:
lib.parseFunc_RTE {
tags.img = TEXT
tags.img {
current = 1
preUserFunc = Netresearch\RteCKEditorImage\Controller\ImageRenderingController->renderImageAttributes
dataWrap = |
}
}
The problematic part is here: title="file:{parameters:data-htmlarea-file-uid}:title"
I've tried using {file:{parameters:data-htmlarea-file-uid}:title}, but it still doesn't work and shows error within rendered element:
The only working example is when I hardcode the UID ({file:120:title}), but it should be added dynamically, as there are many images.
How can I escape this "double variables"? Or maybe there is another solution to make it work?
==================================================
Here's the full solution of my problem, thanks to #Jo Hasenau
lib.parseFunc_RTE {
tags.img = COA
tags.img {
10 = TEXT
10 {
dataWrap = file:{parameters:data-htmlarea-file-uid}:title
wrap3 = <a href="{parameters:src}" class="lightbox" title="{|}"
insertData = 1
}
20 = TEXT
20 {
dataWrap = file:{parameters:data-htmlarea-file-uid}:description
wrap3 = data-lightbox-caption="{|}" data-lightbox-width="{parameters:width}" data-lightbox-height="{parameters:height}" rel="lightbox-group">
insertData = 1
}
30 = TEXT
30 {
current = 1
preUserFunc = Netresearch\RteCKEditorImage\Controller\ImageRenderingController->renderImageAttributes
wrap = |</a>
}
}
}
You can use dataWrap and/or insertData multiple times either by using the official order of stdWrap functions or by squeezing in another "level" of stdWrap functions with stdWrap.functionName
In this case it's the order of functions combined with a COA to separate the original wrap into smaller chunks and some additional braces provided by another wrap.
lib.parseFunc_RTE {
tags.img = COA
tags.img {
10 = TEXT
10 {
preUserFunc = Netresearch\RteCKEditorImage\Controller\ImageRenderingController->renderImageAttributes
dataWrap = file:{parameters:data-htmlarea-file-uid}:title
wrap3 = <a href="{parameters:src}" class="lightbox" title="{|}" data-lightbox-caption="{file:120:title}" data-lightbox-width="{parameters:width}" data-lightbox-height="{parameters:height}" rel="lightbox-group">
insertData=1
}
20 = TEXT
20.current = 1
20.wrap = |</a>
}
}
preUserFunc will be executed first, then the first dataWrap will create the actual variable name, followed by wrap3 to get the necessary curly braces, finalized by insertData to fill in all the other variables together with the generated variable.
The order in this code is just for better readability, but the actual order of function calls within stdWrap is predefined in the PHP code and follows exactly the order of function descriptions in the official docs: https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/Functions/Stdwrap.html

Typoscript modify a field:variable

I have this typoscript:
tt_content.gridelements_pi1.20.10.setup {
3cols.outerWrap = <div>|</div>
3cols.outerWrap.override.insertData = 1
3cols.outerWrap.override = <div id="{field:tx_cewrap_id_input}" class="{field:tx_cewrap_class_input} {field:tx_cewrap_class_select}">|</div>
3cols.outerWrap.override.if.isTrue.field = tx_cewrap_active
}
Which makes sure a wrapper is made around a certain element. The following html is generated as an example:
<div id="" class="full-box full-box-features container pt-75,pb-75"></div>
As you can see there is a comma separated string inserted as "tx_cewrap_class_select". With the {field:tx_cewrap_class_select} part:
pt-75,pb-75
But i want the comma to be a space character so the classes work in html
Now I know about the split option
But how do I fix the code, just need somehow to remove the comma! That's it :)
Thanks in advance for any response I can use.
You can split by comma and join with a space, but in this case it might be easier just to replace the comma by space:
10 = TEXT
10.replacement {
1 {
search = ,
replace.char = 32
}
}
And here the solution with split. it should be obvious why not to use:
10 = TEXT
10.split {
token = ,
cObjNum = 1 || 2
1.current = 1
2.current = 1
2.noTrimWrap = | ||
}
Hint:
on TEXT you can use stdWrap functions immediately,
in other context you might need an explicit .stdWrap:
10.stdWrap.replacement {
10.stdWrap.split {
Either you prepare your values into a register for later use, or you split your override value into a COA. You even might use the replacement on the whole override value in case you are sure no other comma might be needed.
COA-Solution:
(don't forget the noTrimWrap for 20 otherwise the classes are appended without space)
override.cObject = COA
override.cObject {
10 = TEXT
10.value <div id="{field:tx_cewrap_id_input}" class="{field:tx_cewrap_class_input}
10.insertData = 1
20 = TEXT
20.field = tx_cewrap_class_select
20.replacement {
1 {
search = ,
replace.char = 32
}
noTrimWrap= | ||
}
30 = TEXT
30.value = ">|</div>
}

How can I make a Condition in TypoScript for loading different JavaScript-Files to different Backend-Layouts? (TYPO3)

After a "long way" with Google, Searching and many tries:
I created a lib.variable for the current Page:
lib.currentPage = TEXT
lib.currentPage.data = page:uid
If I debug it in my FluidTemplate in the Frontend with:
Testing currentPage: <f:cObject typoscriptObjectPath="lib.currentPage" />
I got the correct value.
Now I want to use that Variable in a Condition in my pageSetup.ts like follows:
[DB:pages:lib.currentPage:backend_layout = pagets__pagelayout_logoclaim_subpage]
page.includeJSFooter.belayoutlogoclaim = EXT:rm_base/Resources/Public/JS/be_logoclaim.js
[end]
I testet this with some other Conditions, but nothing works like expected.
Tested Conditions:
[page|backend_layout = pagelayout_logoclaim_subpage]
[globalVar = TSFE:page|backend_layout = pagelayout_logoclaim_subpage]
I also tested the Condition in the TypoScript Object Browser, and here it looks like good working:
TypoScript Object Browser - If I activate the Condition
SourceCode in the Frontend on a Site with the correct PageLayout
I need this, because I have two different Menus, and they need different JavaScripts, to avoid wrong behaviour in the Frontend.
Update:
I inserted the pageLayouts like this:
page = PAGE
page {
10 = FLUIDTEMPLATE
10 {
partialRootPath = EXT:rm_base/Resources/Private/Templates/Fluid/Partials/
layoutRootPath = EXT:rm_base/Resources/Private/Templates/Fluid/Layouts/
file.stdWrap.cObject = CASE
file.stdWrap.cObject {
key.data = pagelayout
// Default-Template is LogoFull_Subpage (No Navigation Dependence)
default = TEXT
default.value = EXT:rm_base/Resources/Private/Templates/Fluid/LogoFull_Subpage.html
// LogoClaim - Subpage
pagets__pagelayout_logoclaim_subpage = TEXT
pagets__pagelayout_logoclaim_subpage.value = EXT:rm_base/Resources/Private/Templates/Fluid/LogoClaim_Subpage.html
}
}
You see: The Backendlayouts are in Files of my Extension, not in the Database-Table: backend_layouts.
Update 2:
I would prefer a TypoScript-Way, if someone knows how - with external BE-Layouts. Thank you.
As I've seen the prefix pagets__ ,I guess that the problem here is that the backend_layouts are not stored in the database, so I think that a condition about that would not work.
If you are using a different html template for each backend layout and you are running TYPO3 8.7.x there is a different way to solve this issue: Add to your template file a new section called:
<f:section name="FooterAssets">
<!--your code here-->
</f:section>
This section will be loaded just before the closing of </body>. As far as I remember you don't even have to call this section in your layout file.
i would opt for using the VHS extension which provides an asset viewhelper.
you than include the asset view helper into the frontend template you are rendering. and it takes care about plaching the javascript in the header / footer
it allows also to definde dependancies and loads the script in the correct order. also supports concatination / minification ...
an example include might look like this:
<v:asset.script path="EXT:your_ext/Resources/Public/JavaScript/menu_a.js" dependencies="jquery" />
this requires you that you specified "jquery" via typoscript (or another assit view helper)
example typoscript:
plugin.tx_vhs.settings.asset.jquery {
path = EXT:your_ext/Resources/Public/JavaScript/jquery.js
type = js
}
I found another solution, that uses a TypoScript Custom Condition:
First I create a BackendlayoutCondition.php in my Extension here:
/Classes/TypoScript/BackendlayoutCondition.php
Its content is this (See Comments for more Detail):
<?php
namespace RM\RmBase\TypoScript;
use \TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractCondition;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;;
class BackendlayoutCondition extends AbstractCondition
{
/**
* Evaluate condition
*
* #param array $conditionParameters
* #return bool
*/
public function matchCondition(array $conditionParameters)
{
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($conditionParameters,'cond Params');
# Return false if in Backend (Condition for Frontend only)
if (!$GLOBALS['TSFE']) return false;
# QueryBuilder for Table: pages
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
# Check if current BackendLayout is inside the $conditionParameters
if (!empty($conditionParameters) && substr($conditionParameters[0], 0, 1) === '=') {
# Trim the Parameter to get the correct Value of the Parameter (behind '=')
$conditionParameters[0] = trim(substr($conditionParameters[0], 1));
# Get Backendlayout on this Page
$backendLayoutOnThisPage = $queryBuilder
->select('backend_layout')
->from('pages')
->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter(intval($GLOBALS['TSFE']->id), \PDO::PARAM_INT))
)
->execute();
# Store Backendlayout Value of the current Page in $backendLayoutOnThisPage
$backendLayoutOnThisPage = $backendLayoutOnThisPage->fetch()['backend_layout'];
} else {
# If no ConditionParameter was set return false
return false;
}
# Check if parent BackendLayout_NextLevel is inside the $conditionParameters
if ($backendLayoutOnThisPage == '') {
# Get pageRepository
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$pageRepository = $objectManager->get('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
# Get Rootline of the current Page
$pageRootline = $pageRepository->getRootLine(intval($GLOBALS['TSFE']->id));
# Set rootlineIndex to the Parent Page Index
$rootlineIndex = count($pageRootline)-2;
# Check Parent Page Backendlayout_NextLevel till 0 or Backendlayout found
while ($rootlineIndex > 0) {
if ($pageRootline[$rootlineIndex]['backend_layout_next_level'] == $conditionParameters[0]) {
return true;
} else {
$rootlineIndex--;
}
}
# No BackendLayout_NextLevel found till 0
return false;
} else {
# If Condition Backendlayout found return true, otherwise return false
if ($backendLayoutOnThisPage == $conditionParameters[0]) {
return true;
} else {
return false;
}
}
}
}
(Edited 2)
Than I just have to use the following Condition in my pageSetup.ts:
[RM\RmBase\TypoScript\BackendlayoutCondition = pagelayout_logoclaim_subpage]
page.includeJSFooter.belayoutlogoclaim = EXT:rm_base/Resources/Public/JS/be_logoclaim.js
[global]
Now I have this Sourcecode in the Frontend:
<script src="/typo3conf/ext/rm_base/Resources/Public/JS/be_logoclaim.js?1523005944" type="text/javascript"></script>
not that:
<script src="/typo3conf/ext/rm_base/Resources/Public/JS/be_logoclaim.js" type="text/javascript"></script>
if I use the FooterAssets method:
<f:section name="FooterAssets">
<script src="/typo3conf/ext/rm_base/Resources/Public/JS/be_logoclaim.js" type="text/javascript"></script>
</f:section>
Edit: I found some errors in my Answer, i fix it and edit my answer then.
Edit2: Now the Condition checks the Backendlayouts and the Backendlayouts_Nextlevel Fields for Backendlayouts to get all possible BE-Layouts including the inherited.
The problem with the backend_layout field is that there also is a field backend_layout_next_level which affects subpages. so you can't build a simple condition.
Either you use stdWrap.if where you can calculate the current value for backend_layout overlaying an inherited value from backend_layout_next_level.
Or you define a userfunc where you evaluate it yourself in PHP.
Be aware that layouts defined in records have another prefix than layouts defined in pagesTS.
edit:
Example
temp.layout = CASE
temp.layout {
key.data = levelfield:-1, backend_layout_next_level, slide
key.override.field = backend_layout
default = TEXT
default.value = default-layout
1 = TEXT
1.value = layoutdefinition_from_record
pagets__layout2 = TEXT
pagets__layout2.value = layoutdefinition_from_pageTSconfig
sitepackage__layout3 = TEXT
sitepackage__layout3.value = layoutdefinition_from_sitepackage
}
Now you can use temp.layout for further decisions:
10 = TEXT
10.field = bodytext
10.wrap = <div class="demo">|</div>
10.wrap.if {
equals.cObject < temp.layout
value = default-layout
}

How can I create a link to a specific, known page using TypoScript?

I am working on some Typo3 6.2 templates. I want to insert a link into the template using Typoscript.
I have a constant {$HOME_SHORTCUT}, which has the title "Startseite" & the path /start. I want the link to look like this:
Startseite
I am using this to insert the link before a set of breadcrumbs. The link path is correct but the value/text of the link is the pageID of {$HOME_SHORTCUT}, not the header text, which is what I want:
stdWrap.prepend = TEXT
stdWrap.prepend {
value = {$HOME_SHORTCUT} ###HOW DO I USE THE TITLE OF THE PAGE AS THE VALUE?####
stdWrap.typolink {
field = header
parameter = {$HOME_SHORTCUT}
}
}
This outputs:
146
Which is incorrect. That's the page ID, not the header. How do I get the header of {$HOME_SHORTCUT}?
When you leave out the "value" the page title is set automatically:
stdWrap.prepend = TEXT
stdWrap.prepend.typolink.parameter = {$HOME_SHORTCUT}
Following along with this answer, I constructed this, which gives the desired mark-up:
stdWrap.prepend = TEXT
stdWrap.prepend {
value {
table = pages
select {
where = uid = {$HOME_SHORTCUT}
}
renderObj {
10 = TEXT
10 {
field = title
wrap = |
}
}
}
stdWrap.typolink {
field = header
parameter = {$HOME_SHORTCUT}
}
}
Which seems like a really, really long-winded way of saying "Wrap this page title with a link to this page"- I am definitely interested in hearing of better methods.