AFAICT, there is not a way to exclude certain translatable fields from being been seen as translatable by TMGMT. The ability to exclude such fields either, programmatically or through the UI, would be an useful addition to TMGMT. An entity may contain fields that hold data they are strictly for layout or presentation purposes. These fields may still be translatable to allow for localization of their data per local, but it may not be appropriate to have these fields included when entity data are handled through TMGMT and its providers.
Use case: A site has a content type that contains a Block Quote paragraph entity. This Block Quote paragraph has text fields title, body, and background color name. All of these fields are configured to be translatable so that their contents can vary by locale, but only the title and body fields should be processed by TMGMT, while the background color name field will be edited directly by site editors at their discretion (and its value used in the theme layer).
Found the below @TODO: in the module code:
/** * Extracts translatable data from an entity. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity to get the translatable data from. * * @return array $data * Translatable data. */ public function extractTranslatableData(ContentEntityInterface $entity) { // @todo Expand this list or find a better solution to exclude fields like
Comments
Comment #2
gg4 CreditAttribution: gg4 commentedComment #3
gg4 CreditAttribution: gg4 commentedComment #4
gg4 CreditAttribution: gg4 commentedComment #5
gg4 CreditAttribution: gg4 commentedComment #6
BerdirSounds like a useful feature. I think it could work in a similar way as the embedded fields setting that we already have. The UI might not scale if we show dozens of fields in a checkbox though, might need some kind of custom autocomplete instead, or expose it on the field settings page.
Comment #7
sorinb CreditAttribution: sorinb as a volunteer commentedSeems to be a useful feature in plan of UI to add it there.
Comment #8
sorinb CreditAttribution: sorinb as a volunteer commentedPer @bonus originally stated method "extractTranslatableData" I started to dig more into fields exclusion and noticed the following condition inside of this method:
Basically, getType() returns the entity plugin type, ex: text, while we need to target on getName() which relates to field machine names definition and it makes sense to exclude the fields based on their machine_names rather than Plugin Types.
So, the code should look like:
So this will lead to a more granular approach or we can combine both.
Comment #9
BerdirNo, you don't want to replace that, we still want to exclude some field types. But extend that logic with a field name based exclusion list, either as a third party settings flag (would only work for configurable field definitions) or a global list, similar to the embedded field list.. sure, why not.
Comment #10
Soul88@Berdir, what do you think about the possibility to give access to $translatable_fields list through some alter hook? So that other modules could filter/alter this list according to their own logic?
Comment #11
BerdirSure, that's fine with me. Still think a setting would be useful as well, but a hook makes sense either way.
Comment #12
Soul88Ok, so to start something with:
Comment #13
Soul88Comment #14
BerdirThanks.
Missing . at the end.
we usually don't put @see on issues in the docs unless they provide important information which I think is not the case here.
Also, @see would have to be after @param, after an empty line.
type is required for all arguments and must be fully qualified
arguments to hook-documenation-functions should also use the full namespace so they are easier to copy into a module.
Comment #15
Soul88Thanks for the quick review! Fixed suggestions above.
Comment #16
sorinb CreditAttribution: sorinb as a volunteer commentedHI Guys,
I will submit smth for review as well shortly. Added some UI/UX approach for the user per FieldConfig.
Will post shortly.
Comment #17
sorinb CreditAttribution: sorinb as a volunteer commentedAttaching patch which includes the UI approach through ThirdPartySettings.
Comment #18
BerdirThanks. Conceptually on the right track but quite a few things to clean up and improve.
Also, the two patches should be combined into one. And we'll need tests, at least for the third party settings part, I can live with not having tests for the hook.
this seems wrong, the third party setting is on the field config entity, not node types.
You should check for the interface with instanceof: "if ($field_definition instanceof ThirdPartySettingsInterface) {"
Also check coding standards, like in my example above with spaces.
I don't think we need a separate method for this (which would need proper documentation).
Can't we do this inside the existing array_filter() callback?
What we could do is make the anonymous function for array_filter() an actual method on this object, but this shouldn't get that complicated.
For example, we could refactor it to separate the checks into 3 different ifs. if not transable, return false. if excluded field type, return false. if implements that interface and the checkbox is enabled, return false. end with return true.
hook implementations don't need to document their params.
This should live in tmgmt_entity.module, not in tmgmt.module itself, that doesn't know anything about fields.
I think we usually don't use TMGMT in UI text, not sure about adding this here.
The first argument to getThirdPartySetting() and all related methods is the module name.
I'd also leave out params here, also this is not a hook but an entity builder callback. And I'd just entity_builder in the function name.
And $type should be $entity
Comment #19
gg4 CreditAttribution: gg4 commentedFWIW, the hook @Soul88 implemented seems to be working as expected. I testing with the
moderation_state
field provided by Workbench Moderation and a custom text field. I agree with @Berdir that there is probably benefits to implementing both a UI third-party settings based approach and keeping the alter in place as well.Comment #20
sorinb CreditAttribution: sorinb as a volunteer commentedThanks @berdir for your prompt review and feedback. I fall in agreement with all stated above and will work on refactoring based on comments and roll-out the updated patch including them.
Kind regards,
S.
Comment #21
sorinb CreditAttribution: sorinb as a volunteer commented@berdir, could you please review the re-created patch bellow.
Meanwhile, will work on tests for it.
Thanks!
Comment #22
BerdirWhen making changes to an existing patch, please provide an interdiff: https://www.drupal.org/documentation/git/interdiff
How is it going with the tests?
Comment #23
sorinb CreditAttribution: sorinb as a volunteer commentedHi Berdir,
thanks for following up - I was a bit off with other things, but now I'm back.
I took a look into CrudTest file, but there is a think which creates questions.
While I use thirdpartysettings for setting up excluded from translation property on entity in real world versus the for example "testAddingTranslatedData", where the test data is generated and not taken from real world (real fields/entities), which is fine and should not intersect with each other...
I'm not sure how to fake the field with excluded property for my test case.
Would appreciate if you can drop a suggestion?
Thanks
S.
Comment #24
BerdirSorry, I don't understand your question.
The entities and fields within the tests are 100% real, just like on a real website. You can edit them and add third party settings through the API, just like you do with the form.
Comment #25
sorinb CreditAttribution: sorinb as a volunteer commentedHi @Berdir, sorry for a delay on this one. But I have some issues with tests:
1. I ended up creating a custom content type in tmgmt_tests module, so I could work with real fields. Also, while we use clean profile to run tests this was required to be done so.
2. When I run the tests, I'm under impression that content type does not get created in test environment, while if I try it locally by enabling tmgmt_test module it appears.
I'm testing content types through following method:
$node_types = \Drupal\node\Entity\NodeType::loadMultiple();
dd($node_types, 'types');
while running the test and it returns empty in test env, while on local it is fine.
Would appreciate any insights if you could help to better understand this test env behavior.
Thanks,
S.
Comment #26
Berdir1. No, it really shouldn't be needed. Again, the fields that we create in the test are 100% real, they just have dynamic names and are for dynamically named node types.
For example in \Drupal\Tests\tmgmt_content\Kernel\ContentEntitySourceUnitTest::setUp, all you need to do is something like this:
I copied this from the existing field definition, I only changed the name, field type and added the third party settings call. Now you have a field that will be ignored.
You just need to set a value for it a bit below with $translation->ignored_field->value = 'This must not be translated';
And then you can assert later below that ignored_field is, unlike field_test_text and image_test *not* in $data and you're done.
Also, just noticed one more thing in the patch.. true/false must be upper case.
Comment #27
hitfactory CreditAttribution: hitfactory commented+1 for this feature.
Attaching updated patch which includes test stuff and some minor tweaks. Hopefully it can help move it along.
Comment #28
gg4 CreditAttribution: gg4 commented\
Comment #29
BerdirThanks, looks good, just coding standards issues mostly to clean up.
some trailing spaces here.
Same here. Noticed this in the redirect patch that you worked on as well, consider configuring your editor/IDE to remove those.
why 0 as default value and not FALSE? And why not just if ($is_excluded), the variable is always defined and either true or false already.
also here, use TRUE
leading \ missing for the class names, fields are FieldDefinitionInterface, not just base fields. And desription is also needed.
since the builder is a callback, @params are IMHO not needed, they're also not correctly formatted.
you can actually write this in 1-2 lines again, setThirdPartySetting($exclude_from_translation)
Comment #30
hitfactory CreditAttribution: hitfactory commentedThanks for reviewing, @berdir.
Attached patch addresses all of the above. Tweaked my editor settings and also removed some brackets and use statements which were added in the original patch in #20 but whose classes I couldn't see being referenced anywhere.
FYI, when I ran, ../../vendor/bin/phpunit --group tmgmt, I got an error about missing configuration schema, but I haven't addressed that.
1) Drupal\Tests\tmgmt_config\Kernel\ConfigSourceUnitTest::testView
InvalidArgumentException: The configuration property display.default.display_options.filters.job_type.group_info.group_items.1.value.value doesn't exist.
Comment #31
BerdirThat config error sounds like you were on 8.2, I think the tests only work with 8.3+.
Thanks, looks good to me now, committed.