TCA configuration: Value of field should be copied to translated record - typo3

I am adding a field to the pages table (is a relation to a file) and would like the value of the field in the pages record to be copied to the translated record by default.
Currently, the copied field is empty (default value), which is probably a good idea in most cases.
I am thinking of something that behaves like l10n_mode = prefixLangTitle without the prefix.

Depending on the TYPO3 version this should be possible with one of the following behaviours for the inline field:
https://docs.typo3.org/typo3cms/TCAReference/7.6/Reference/Columns/Inline/Index.html#behaviour
https://docs.typo3.org/typo3cms/TCAReference/8.7/ColumnsConfig/Type/Inline.html#localizechildrenatparentlocalization
https://docs.typo3.org/typo3cms/TCAReference/latest/ColumnsConfig/Type/Inline.html#allowlanguagesynchronization
Sine the localizeChildrenWithParentLocalization feature is broken with pages and pages_language_overlay though, I guess the only working versions would be CMS 8 or 9 with properly configured language synchronization.
https://forge.typo3.org/issues/78743

Use
['behaviour']['allowLanguageSynchronization'] => true
if the translated record will use the value from the default field by
default (will effectively be copied), but it should be possible to change
this later.
See pages.author as example.
When "Custom value" is selected, the value can be overridden.
Alternativively, use
l10n_mode = exclude
if the field should always have the value of the default language and you
should not be able to change it in the translated record.

Related

Typo3 v10: Fix Translated ContentElements within Gridelements with language=all

I'm using Typo3 10.4.28 with gridelements 10.4.3 (not w/DataProcessing)
To minimize redundancy in a Multilanguage-Site I set Content Elements (CE) without own Text-Content to language=all and translate only CEs with Text.
It feels very logical and useful to me, to set language=all on gridcontainers (where I'm not using its title or other own text-fields), to be able to set contained Plugins, Menu-Elements and Images to Language=all, even if it also includes a translated Text-CE
(and I have seen this done in a Typo3 with gridelements where I have only regular backend access and don't know exactly how they achieved that).
But when translating CEs within language=all gridelements, this is not rendered correctly in the frontend on the translated page.
Translated CEs are either rendered twice (fallbacktype: strict/fallback) or all language versions are rendered (fallbacktype: free).
According to gridelements maintainer #Jo Hasenau, putting translated elements into language=all containers is not supported directly with unmodified gridelements.
Thanks to his comments I found a setup which (while hacky) works more or less:
fallbacktype: free
[siteLanguage("languageId") == 1]
lib.gridelements.defaultGridSetup.columns.default.renderObj.20.stdWrap.if {
isInList.field = sys_language_uid
# -1 is language=all
value = -1,1
}
[GLOBAL]
# allows only content in the correct language or "all"
# repeat for each other languageId
I found a problem with this setup though: in free-mode, translated elements get ordered in frontend based on their own "sorting" instead of their original element's. This means, translated elements might switch places with Language=all elements, compared to the default language. Fixing this in (translated) content would be a big hassle on a large site.
So I tried to find a fix for fallbacktype: strict
(where "you get the original element with a translation overlay and after that the translation itself")
lib.gridelements.defaultGridSetup.columns.default.renderObj.20.stdWrap.if {
isFalse.field = l18n_parent
}
I hoped this would exclude only "the translation itself", but sadly it also excluded the "translation overlay". In fact both seem to be identical to typoscript at this point.
Update:
A pure TS-Solution for strict and fallback is found, and my above solution for free technically works as well (free is just not suitable), so this case seems closed.
A small word of warning for anyone who wants to use this structure, though:
sys_language_uid -1, aka Language All might be removed from Typo3 in upcoming versions:
https://decisions.typo3.org/t/rethinking-translation-handling-based-on-a-session-of-t3cmd-2022/734/16
As discussed in the Gridelements issue tracker, you should go for strict or fallback mode, since free can not work by definition.
Still your approach with strict is wrong, since you don't have to include the target language records, but only default language records or those that got language all but after the translation overlay.
This overlay will add a virtual field named _LOCALIZED_UID
Reason: Both strict and fallback use overlays to render their content, and since there always is a record of the default language available, this will be the one to fetch, while the content will then be overlaid.
So the solution should be:
[siteLanguage("languageId") > 0]
lib.gridelements.defaultGridSetup.columns.default.renderObj.20.stdWrap.if {
isFalse.field = _LOCALIZED_UID
value = -1
isGreaterThan.field = sys_language_uid
negate = 1
}
[GLOBAL]
Without additional conditions, since it will be the same for any target language.
To explain the Syntax you need to know, that the TypoScript if-conditions only know AND but not OR, so if you want the result of an OR condition you need to negate the opposite AND condition, which is what the snippet does.
It checks for a non existing _LOCALIZED_UID and the language of the record being greater than -1 - and if this is both true, it will negate the result. If any of the conditions is false, the negated result will be true.
Basically this is the same behaviour as with pages, which are kind of top level containers themselves.
If you want just one single element of that page to be translated, you need to create a translated page record before. So having a page with the "language => all" behaviour will only work together with a properly configured fallback, if there is no translated content on that page at all.
So you don't have to switch the frontend rendering TS template, but just follow the rule you already described.
I set Content Elements (CE) without own Text-Content to language=all
and translate only CEs with Text
Since a Gridelements container is a CE and the child elements are basically content of that CE, just as with pages you always have to translate a container element as soon as it contains at least one translated element.
So language "all" should only be applied to containers that don't contain any translated child element at all.

Vue Element UI - Default el-input-number to empty field instead of a number

Creating a form with no values and would like the input field to default to empty for two reasons:
Want users to be able to see the placeholder text.
Having a default number means the users can ignore the field by default. (I know I can validate the field, but that is just a bad user experience.)
The problem:
el-input-number fields default to a number (0 or whatever the :min value is set to).
This covers up the placeholder text.
The users can click save with the default number still in place. (I will validate, but don't want users to have to submit a bad value to know what to do.)
Does anyone know how to make the input field have the default value be just empty?
just give it a default value of undefined
https://codepen.io/rugia/pen/bGEoWaB?editors=1010

How to remove a field from `showitems` in TCA?

TYPO3 has the function TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes() to add or replace one or more fields to the BE form of a record.
How can we remove fields?
(replacing by '' does not work)
Explanation:
Its about hiding some fields in tt_content for some CTypes only.
In the past we did it by overwriting the complete value. But with the upgrade from 6.2LTS to 8LTS we run into problems as the default labels have changed (pathes to the language files) and so some labels become lost in the BE, which was noticed very late.
Now I want a clean way to remove single fields so that the definition of the remaining fields stays clean with the default values from core (or other extensions).
Other extensiosn which add their own fields also are a problem if the value is set with a static string: these fields are also removed.
Since there is indeed no way to insert an empty string, you could create an empty palette instead. This way you will still get a non empty string to insert, but it will not create any output in the form.
addToAllTCAtypes('table', '--palette--;;empty', '', 'replace:fieldname')
And you should make a feature request, to make at least the replacement with an empty string possible in upcoming versions of TYPO3.
Do it in the code like this:
foreach ($GLOBALS['TCA']['yourtablenamehere']['types'] as &$definition) {
$definition['showitems'] = '';
}
if you only need to reset a specific type ('0', for example):
$GLOBALS['TCA']['yourtablenamehere']['types']['0']['showitems'] = '';
If you want to override types completely instead of clearing them (clearing only does not much sense anyway):
$GLOBALS['TCA']['yourtablenamehere']['types']['0']['showitems'] = 'title, bodytext';

TYPO3 Not able anymore to translate CE's to other languages

Is there a way to 'reset' or db entries to delete or something else without deleting all content already translated... (and would that solve the issue?)
In the first go all translation went well, I chose a 'one tree' setup pressing translate rather then copy, but adding and modifying the content over time certain elements where not available for translation anymore ...
at one point the second step in translation asked for the origin language (if I recall well) and trying to resolve I chose another language than the default, now I do not have the choice anymore and the record summary proposes elements from german rather than from my default language (italian) which might be the problem since I can only introduce new content in the default language.
if I try to localize from the list view clicking the language flag, in the language selection field I get [INVALID VALUE("1")] and as only option (Default) [0] to select ...
I use TYPO3 V7.6.13, EXT:gridelements and EXT:t3sbootstrap (the nested CE's where the first to show trouble)
content of my database table sys_language: (my default lang is italian)
uid | pid | tstamp | hidden | title | flag |
1 0 ... 0 English gb
2 0 ... 0 German de
does anyone know good reference or a solution to this problem ?
That sounds like your sys_language records (in yoour root-page, id = 0) are disabled or missing.
Those records make languages available for translation.
The other factor for translation selection is the translation of the current page. You need to have the page translated to a language (given above) to be able to translate any record in that page. That also is neccessary for pages which contain only data.
first check (as suggested by bernd) if your language setup is valid:
do you have a sys_language record for every added language in your
root-page ? (you can control the sys_language table with phpMyAdmin)
is the page translated ?
in my case that was all fine but I needed a thorough cleanup:
I deleted all hidden records in the backend
I activated the system extension 'recycler' and deleted all in the
list (from root-page recursive)
I then checked with phpMyAdmin which records in tt_content where
hidden (and did not show in the backend) and deleted those manually
once I did that the translate request answered perfectly and I could restore the missing CE's translations
note: I still had gridelements showing up in wrong sequence for the translation in the backend but correctly in the frontend, the nested CE's seem though, and of course 'CLEAR CASH FREQUENTLY' to avoid surprises ...

jQuery: Select all 'select' elements with certain val()

Does anyone know of an easy way, using jQuery, to select all <select> elements whose val() attribute yields a certain value?
I'm trying to do some validation logic and would like to just select all those elements with a single selector, then apply a warning class to each of their parents. This I know how to do once I select all the elements, but I didn't see a selector that handles this case.
Am I going to have to select all of the <select> elements into a selector, then iterate through them and check each of their values? I was hoping there would be a simpler way.
Thanks.
Why doesn't select[value=x] work? Well firstly because <select> doesn't actually have a value attribute. There is not a single value of a select box: there may be no selected options (there shouldn't normally be, but there can be in at least IE), and, in a <select multiple>, there can be any number of selected options.
Even input[value=x] doesn't work, even though <input> does have a value attribute. Well, it does work, it just doesn't do what you think. It fetches the value of the value="..." attribute in the HTML, not the current value you have entered into the form. The value="..." attribute actually corresponds to the defaultValue property and not value.
Similarly, option[value=x][selected] doesn't work because it is checking the <option selected> attribute from the HTML source (selected attribute -> defaultSelected property) and not the current selectedness of the option (selected property not attribute) - which might have changed since the page was loaded.
Except in IE, which gets the value, selected etc form attributes wrong.
Except (again): Tesserex's example may seem to work, and the reason for that is that that it's using a non-standard jQuery-specific selector, :has. This causes the native querySelectorAll methods of modern browsers to fail, and consequently jQuery falls back to its own (native JavaScript, slow) selector engine instead. This selector engine has a bug where it confuses properties for attributes, allowing [value=x] to do what you expected, and not fail like it should! (Update: this is probably no longer the case in newer jQuery versions.)
Summary: form field state checking and selectors don't mix. Apart from these issues, you also have to worry about escaping issues - for example, what if the value you want to test against contains quotes or square brackets?
So instead, yes, you should check it manually. For example using a filter:
$('select').filter(function() {
return $(this).val()==='the target value';
}).parent().addClass('warning');
(There is a value property in HTML5 and supported by modern browsers, that when you read it gives you the value of the first selected <option>. jQuery's val() is safe to use here because it provides the same method of getting the first selected option even on browsers that don't support this.)
The existing answers don't work on select tags, but I found something that does. Ask for a select that has a selected option.
$("select:has(option[value=blah]:selected)")
You can use :
$("select[value=X]");
where X is the value against which you want to check the select's value.
Attribute selectors Is what you're looking for I believe.
Something like $+('element[attribute="value"]')
See also:
*= anywhere
^= starts with
$= ends with
~= contains word
etc.
You can create a change event that puts the value in a custom attribute on the select element whenever the value changes. You can then use a simple selector to find all of the select elements that have that value. For example:
$("select").on("change", function (e) {
var $select = $(e.currentTarget);
$select.attr("select-value", $select.val());
});
And then you can do this:
var $matches = $("select[select-value='" + searchVal + "']");
$matches will have all of your matching selects.
This is a lot easier than having to iterate through elements. Remember to set select-value to the initial value when rendering the page so you don't need to trigger a change event for each select so the select-value is set.