I suppose we didn't account for that but it might require a formatter settings as some people may want to show the empty cells at least in a regular table. Honestly I think I may have left it open for something more advanced (like optional fallback value). I'll come up with something for the next release and perhaps a patch soon when i get a chance.
apmsooner → created an issue.
apmsooner → created an issue.
My opinion is still that it would be better to allow Multi-value in a subfield.
It's not technically even possible due to how the data is stored. You'll notice there is no cardinality setting at the sub-field for this very reason, only single values can be stored in a table row. So, its not a choice.
Custom field is not always going to replace paragraphs or entity_reference field. If you need multi-valued entity references and don't need any other complementary fields with them, just use entity_reference. If you need multiple single value fields grouped together, use custom_field. If you need both, you can use a paragraph containing the best of both worlds: multi-valued entity_reference field + custom_field.
I can assure you there is a performance benefit with custom_field vs. multiple regular fields purely based on the fact that regular fields are all stored as individual tables. Paragraphs only compound the problem by introducing more tables and revision bloat. That being said, you have to have balance in your application based on what you need.
I've looked into replicating what the Geofield module https://www.drupal.org/project/geofield → is doing and it would just be way too heavy of a lift to handle this in custom_field. This particular need makes much better sense to just split out as its own field. If these fields should go together as a multi-valued component or you just want them structured together for API reasons, I would still use a paragraph here as an entity wrapper that contains both fields, otherwise just split them out as separate single values on the node or whatever parent entity type the fields are attached to.
BTW, what admin theme are you using and what is the version of Drupal Core you are on? The storage and widget settings sections should not be floating together like that and breaking up the table.
Although the autocomplete widget makes it look like you can add more than 1 value, this isn't possible with sub-fields which is why you're only seeing 1 value saved. While a custom field at the field level can be multiple, there will ALWAYS only be a single value allowed in a sub-field. What you're trying to do here looks to be one of those edge cases where you'd want to use a regular multi-valued entity reference field type. We actually discussed this topic in the Talking Drupal episode if you want more insight around why: https://www.youtube.com/watch?v=dC5ec8FG6vQ
However when I add date "18-June-2025 at 21:00" it stores it in database as "18-June-2025 at 11:30" UTC and reports shows that engineer completed task before it was scheduled.
With this scenario, assuming you enter the date "18-June-2025 at 21:00" and were able to set the timezone to berlin, what value would you expect to see in the widget next time you edit. I think it would be 18-June-2025 at 13:00 which in US (1:00 PM)? I just don't even know if this would make any sense at all unless we create a completely new field type that actually stores the timezone so maybe then the stored datetime value is always reflected in the widget as the value with the set timezone. And in this case, I would assume you would also need the formatters modified for this option as well but they are currently generic to regular datetime fields so just not really sure how to even accommodate this.
I'm getting back into this and still I guess trying to wrap my mind around what you need here. Are both you as project manager and the engineer setting the value to the same field or are you as project manager trying to set the date value on behalf of the engineer in his timezone? If the latter, I'm guessing you would just want a timezone select with no default value since it wouldn't be saved but you would choose his timezone on save and the actual date saved would be in his timezone but value shown to you would be in your timezone? I'm just confused as to what date you would expect to see next time you edit? Sorry, I'm just really confused with how this would work.
Patch is ready to test.
apmsooner → made their first commit to this issue’s fork.
Add extra test step for custom_field to enable sub-module custom_field_ai.
Reverted this issue in favor of https://www.drupal.org/project/custom_field/issues/3533534 📌 AI translate update extractor Active that will move the extractor into a new custom_field_ai submodule.
The 3.0.x version this issue is tagged to is no longer supported. Noone has reported any issues with 3.1.x versions related to this but if you are seeing issues after you have ensured you have the latest version of the module, open a new issue with detailed steps of how to reproduce, screenshots and/or video would be helpful also. This issue remains closed as it is tagged to an unsupported version.
Thanks for all your work here @svendecabooter! Merging now to dev.
@valthebald,
Everything is working properly for me after recent changes from @svendecabooter so putting back to needs review for others. Probably need to document the need for the core patch somewhere if properties on file/image fields are desired to be translatable but otherwise, I'm having consistent success with this patch.
I figured out the issue I was having and pushed a commit. The original value wasn't being set to the translated entity before being passed to the extractor. Everything now seems to be working now for me with that fix!
Your changes are making it work for me now. I did push up a change to the custom_field patch to prevent the same warning for undefined array key 0. My setup is i have a basic page with an entity reference field to an article node. The article node has filefield, image and custom field. All of them get translated when the basic page gets translated however the only weird thing is the custom field has an image and file subfield. The image alt text gets translated but the target id value doesn't get set for some reason when the translation is driven off the reference extractor. When i translate the article directly, the custom field image and file target ids get set like they should. I can't remember if they were getting set before your update or not. Seems like the original value I guess isn't getting copied over in that case for some reason. Perhaps you can try this same setup on your end with the updated custom_field patch?
No, it was working fine prior to the commit mentioned in #24. Waiting for @svendecabooter to either revert or come up with alternative solution. Personally I think where I left it was adequate and he can build the additional logic for the async lb module on top of that but giving him time to address first.
Revised patch: added base class and interface to accommodate both entity_reference and image. Also updated the patch at default_content to take advantage of new interface. Please test and provide feedback for this to get merged.
I tried messing with it to get past the errors but it seems like its just no longer even creating the translation for the referenced entity at all anymore. Seems you may have stripped out alot of logic that is needed so unless you can revise to get it working, i'd say revert.
@svendecabooter,
I pulled in your changes and I'm getting errors for all the extractors that get called from the ReferenceFieldExtractor. They are all similar to the following.
Warning: Undefined array key 0 in Drupal\ai_translate\Plugin\FieldTextExtractor\TextFieldExtractor->setValue() (line 43 of /var/www/html/web/modules/contrib/ai-3531717/modules/ai_translate/src/Plugin/FieldTextExtractor/TextFieldExtractor.php)
#0 /var/www/html/web/core/includes/bootstrap.inc(166): _drupal_error_handler_real(2, 'Undefined array...', '/var/www/html/w...', 43)
#1 /var/www/html/web/modules/contrib/ai-3531717/modules/ai_translate/src/Plugin/FieldTextExtractor/TextFieldExtractor.php(43): _drupal_error_handler(2, 'Undefined array...', '/var/www/html/w...', 43)
#2 /var/www/html/web/modules/contrib/ai-3531717/modules/ai_translate/src/Plugin/FieldTextExtractor/ReferenceFieldExtractor.php(220): Drupal\ai_translate\Plugin\FieldTextExtractor\TextFieldExtractor->setValue('title', Array)
FYI, The errors are on a different test and seem to be related to this line from what i can tell: https://git.drupalcode.org/issue/drupal-3386915/-/blob/3386915-Fix-savin...
The patch applies clean for 10.5.1. I followed the steps and it works without error. Additionally, combined with patch for AI translate module ( https://www.drupal.org/project/ai/issues/3531717 ✨ Add text extractor plugins for image and link field types Active ) and following the steps outlined there, all translatable properties on image/file fields get translated as the the batch process is allowed to finish due to this core fix.
@svendecabooter,
The custom FieldTextExtractor plugins for the assymetric modules could probably also be included into the ai_translate module, rather than a separate module, but then the FieldTextExtractor plugin might need some extra logic to decide whether the plugin needs to kick in or not.
Maybe this is handled as a third party setting or just simply in the ai config settings. I think the existing lb plugin could then first check for that setting and do call alternative functions or something?
We can document the module version requirement on the project page but I would prefer we stick with the 1.2 version as the source of truth. Otherwise, someone could make their own patch for 1.1 compatibility if really desired. I don't think there is even enough users that are going to be affected anyhow since ai_translate & custom_field usage together is likely gonna be very low at least for now until more people adopt AI.
Re-rolled core patch here for 10.5.x: #25 https://www.drupal.org/project/drupal/issues/3386915#comment-16174131 🐛 InvalidArgumentException: Invalid translation language (en) specified Active to get file/image fields working.
Re-roll #6 for 10.5.x
This issue is with the contrib module ai_translate_lb_asymmetric so moving to proper channel.
@svendecabooter,
I created a patch for custom_field related in this issue. I didn't catch the other contrib module ai_translate_lb_asymmetric... I thought you were originally just talking about the LbFieldExtractor which works now. That contrib module would need to be updated I guess now too but I don't even particularly understand why its a separate module. Can we not solve for it in ai_translate? There's too many moving parts around all these fields and I've finally got everything working as it should now after some refactoring. The reference extractor for example had some hardcoded field types to translate which would never account for custom fields, image, file, etc... so I fixed that.
apmsooner → created an issue.
I can easily patch custom_field to work with the changes and I'll take a look at the layout builder issue, though i had already addressed that one to work. The idea with the MR was to instantiate the plugin with the entity object as configuration instead of having to pass it to all these functions where it's not even necessary in most cases. Generally with this MR, any field type can be supported by just setting the known translatable properties in the getColumns() method and thats it. The rest of the logic should just work from the base class so we eliminate having to duplicate code everywhere.
- The source entity is first determined by the selected Entity type and Bundle
- The Target field depends on step 1 as we need to fetch all fields that exist from those selections
- The Field mapping source is always going to be assumed the source entity from step 1 UNLESS there are entity reference fields that also exist on that entity in which the user will be presented with that option. The option won't even be visible if there are no reference fields.
- I made Target field selection happen before optional Field mapping source because the Target field is always required and it seemed more logical to make optional selections appear last to keep it a step by step selection.
Limitations
The available fields are specifically limited to prevent errors. Here's the thing, if a user is trying to map a body field to a boolean value, the updater would fail because a value of long text can't be saved into a column that only accepts 1/0. Yes, I could make it more freeform and just let anything be mapped but to your point of making it useful for non-developers, a site builder may not understand why their configuration is failing without having a deep understanding of the data storage requirements under the hood.
Token support
Token support has already been introduced in latest release. See screenshot:
https://www.drupal.org/files/project-images/Screenshot%202025-06-30%20at... →
of what this looks like. Token support is limited to string and text mappings for similar reasons around limitations and could technically fail still if too long of a value from the token is inserted into a string field that only allows 255 characters. But anyhow, it provides some additional flexibility to perhaps set some deep nested values from paragraphs or combine multiple values, etc...
There's room to enhance further with additional widgets and validation for the custom value option but the main focus for now was just being able to map like to like values over to a "custom field" and eliminate unnecessary tables, config, etc...
It's extremely difficult to document "quick start" steps for variable forms and different audiences. When I get a chance, i will put together a video that truly shows how simple this module is. Even site builders should know how to create a very basic custom module that serves purpose of providing an update hook. If you think that most don't and theres not good resources out there to instruct then I will start creating videos for all these tasks we take for granted. I was a "site builder" for many years so I can certainly understand and bridge the gap. As for you, thank you for the feedback! Please get a slack account and engage with the community. Drupal could be so much better with people actually getting together and actually talking through ideas and solutions. I'd say the most frustrating thing as a developer is the sheer lack of communication from the audience using our modules. I'm personally just not gonna let issues sit in a "needs review" status or try to help someone solve a bug with no response so at least your comments here are very helpful.
Updated steps. The module audience is generally developers but the steps are pretty simple enough to follow as is for even beginners so calling this good.
Clarification provided in comment around fields shown. Token support provided for custom value field types of text/textarea.
apmsooner → created an issue.
nicxvan → credited apmsooner → .
Everything should work in this branch for AI translate's role. The 1 caveat is file/image properties that is a core bug: https://www.drupal.org/project/drupal/issues/3386915#comment-15228372 🐛 InvalidArgumentException: Invalid translation language (en) specified Active . I don't know how if we would want to reference the patch being needed to get those field types working or put on hold.
#6 makes my patch for image/file translations work for the AI translate module as mentioned here: https://www.drupal.org/project/ai/issues/3531717#comment-16168671 ✨ Add text extractor plugins for image and link field types Active
Noting here that the patch in: https://www.drupal.org/project/drupal/issues/3386915 🐛 InvalidArgumentException: Invalid translation language (en) specified Active makes file & image fields work.
The link->title & text_with_summary->summary field types are now being translated with this patch. For some reason the file and image field types are failing with this error:
InvalidArgumentException: Invalid translation language (und) specified. in Drupal\Core\Entity\ContentEntityBase->getTranslation() (line 903 of /var/www/html/web/core/lib/Drupal/Core/Entity/ContentEntityBase.php).
Anyone that can help test and find a solution would be appreciated.
This will be handled in this ticket: https://www.drupal.org/project/ai/issues/3531717 ✨ Add text extractor plugins for image and link field types Active
Handled in https://www.drupal.org/project/ai/issues/3531717 ✨ Add text extractor plugins for image and link field types Active . Please help test the patch.
Handled in https://www.drupal.org/project/ai/issues/3531717 ✨ Add text extractor plugins for image and link field types Active . Please follow that issue and help test.
This patch would put a dependency on custom_field module. Needs to just check for the class as string vs. requiring the interface.
@svendecabooter,
Building on my comment in https://www.drupal.org/project/custom_field/issues/3528586#comment-16166705 📌 Support Drupal core DefaultContent API Active , it might just make best sense to create a reference type base class in custom_field that those 3 types extend so that this patch here can just depend on a single class. Forward thinking here in case we were to add new similar data types in custom_field so we don't have to go back and request a change again here.
This looks pretty straight forward enough to merge however in getting back into these data types, I think its probably worth moving this new helper function to CustomFieldDataTypeBase and also the getEntity() function. I would assume for default content api, the other data types: CustomFieldImage & CustomFieldViewfield would also need the same changes and therefore can take advantage of the same methods and changes you're doing for CustomFieldEntityReference?
@svendcabooter - poised above question in #custom-field slack channel. Just confirm if this is the case and whether you have time to make the changes or else I can today and get this merged.
Adding related issue: https://www.drupal.org/project/ai/issues/3529802 ✨ Don't hardcode 'value' key for textual field translation Active . What was merged however will not immediately solve this as the TextFieldExtractor is still just hardcoding the 'value' property. The proper fix would be to use the new '_columns' property similar to what I did in the related custom_field patch (https://git.drupalcode.org/project/custom_field/-/merge_requests/137.diff) so that for that particular field type the 'summary' property would also get translated. Similarly, the link, image, and file field types should be addressed in their own plugins to account for the translatable properties. Basically any field types that have translatable properties other than 'value' would need plugins created.
I suppose it's more or less impossible to reverse the general order, and define data source first, and only then data target, in the second step? (Note, not Paragraph source/target) Because that would logically make more sense, and align with for example rsync (source first, then target). But I assume there are good reasons for the current order, with defining data target first, and only then data source?
Not sure exactly if you mean the main form or mappings. If main form, it's possible to reorder. I guess i put "Target field" first as its always required and the other stuff may not show depending on the fields setup. If you're adamant, i can reverse the order.
Mapping: Some fields seem to be missing
It depends on your field structure of the target and the other fields. The logic matches data types and schema properties to prevent someone from trying to fill a textfield that has a hard length of 255 with a blob of body text. Perhaps its too limiting and adding confusion but the intent was to only show available fields that could actually be properly mapped over and stored without error.
Reverse order on Field source Mapping?
Yes I can certainly make this change. (just pushed a commit for this if you want to refresh).
Feature request: Token support in "Value source" field?
Lets handle this in a separate feature request. I had actually already considered handling token support but just wasn't sure if the community found that useful or not... sounds like it maybe is. I would probably need to limit which target properties could allow this option (e.g. string, text) from source and perhaps do some extra validation during processing to ensure the token value still works with the expected schema. FYI, the custom value source inputs currently match to the targets currently. For instance if you have a boolean data type in a target, you would see a radios TRUE/FALSE widget for the custom value source. And for a textfield, it would have a maxlength property matching the target schema length, and so on. Thats why we would probably need to limit the token support. I alternatively could make an additional dropdown option "Token value" or something and just have a generic freeform input for everything. Again, i would definitely need to validate every value in that case during processing to make sure it can be stored or otherwise skip it and/or log an error. What do you think?
@ressa,
Thank you, I've made several revisions in the dev branch. Tried to revise the updater form with better labels and function to hopefully improve the user experience.
Primary fields to fill:
- Entity type
- Bundle
- Target field
Supplemental fields conditional on field definitions:
- If the selection entity includes a reference field (entity_reference OR entity_reference_revisions):
- Show a "Field mappings source" radios field
- If "Field mappings source" = 'Entity reference'
- Show "Entity reference" select field.
- When selection is made from "Entity reference" field
- Show "Entity reference bundle(s)" field
Drush command has been updated to prompt user to select an updater from list.
Updater logic:
- If an entity reference field is NOT selected as the mapping source, all fields other than reference types from entity will be available to map. If target field is multi-valued, the updater service will track the highest delta from values of all mapped fields and return empty values for any fields that don't have the same delta match. For example, if field_a has 1 value and field_b has 5 values, the target field will result in 5 values with the mapping for field_a filled for the 1st value and remaining 4 empty. All 5 of field_b would be filled.
- If an entity reference field IS selected, the field mappings will be comprised of all fields that exist on the target bundles. The updater logic will only take the first value of each field in this case as we are dealing with multiple entity instances at this point and can't account for multi-valued fields for each bundle.
- If there are no entity reference fields to select from OR the fields mapping source is set to 'Entity', again the mapping fields available and updater logic would be the same as #1.
There were some additional updates also to redirect the form to the mappings on save and some extra validation and such. Let me know what you think?
FWIW, i'm updating the drush command to provide interactive prompt for selecting the updater entity and returning an example update script in the response. For now, I'm going to limit this functionality to Drush as its quite trivial for anyone to run the command for local testing. This module was always intended for a developer audience.
@ressa,
I'm reworking this currently for the source field to only be visible and applicable to 'entity_reference' AND/OR 'entity_reference_revisions' fields on the entity. The updater wasn't ever really supposed to include other field types in the source dropdown which is perhaps where some of the confusion is coming from. I'm interested in your feedback but conversing this way through comments is not real productive. If you are on slack, reach out to me (my handle is apmsooner) and we could do a screenshare and talk through your ideas. I'm going to keep the mappings separate as merging them together into a single form can get overly complicated to handle with ajax and introduce more bugs.
Probably the 'file' field type might be worth mentioning also as there is a description property.
apmsooner → created an issue.
Assuming you've worked this out. There are no other reports of this issue so calling it good.
Tested with updated patch for https://www.drupal.org/project/custom_field/issues/3529794 📌 Add support for AI submodule "ai_translate" FieldTextExtractor plugin Active and it all works perfectly!
You probably just need to add the fields again to the view. There was a new template introduced as noted in this release: https://www.drupal.org/project/custom_field/releases/3.1.8 →
I think this is doable by an optional setting in the widget that would add a timezone select field. The value wouldn't be saved in the db but would be used to just modify the stored datetime presave. I'll see what I can do to make this work.
This last commit seems to be making everything work correctly for me now. Feel free to test it out and see if you're results are also good.
FYI, We can later probably account for entity_reference subfields also in the same extractor similar to the ReferenceFieldExtractor. Does the translation occur in the extract() or setValue() methods? I'm unsure still if this is the best way of identifying the values in the extract() or passing the whole subfield and doing it in the setValue(). It would be better to handle in the setValue() IMO but again... just don't completely understand yet whats happening within these methods.
Just pushed a commit that simplifies things a bit and fixes the link translations issue. The image title/alt is not getting translated now and assume something going on in that loop on line 77 but didn't have time to sort that out yet. You might be able to take it from here though and finish it up based on the revisions I made so far. If not, i can get back into it later.
Okay, i finally got the translate to work in basic form using openai. I was trying with the Groq provider and that was apparently a mistake. I'll pull down your branch for this now and see if I can figure out the remaining issues.
Well I guess I need to figure out how all this works. There's a ton of configuration that makes zero sense to me. I was assuming there was just some button on the node labeled "Translate" or perhaps at the field level. This is a really confusing setup to say the least.
I'll pull your branch down and have a play at it. We can approach this a different way perhaps by targeting the actual specific string properties on the subfields. For example, link & image have specific properties that you'd want to target vs. the actual url or target id. I tried to depict that in the storage outline schema column here: https://www.drupal.org/docs/extending-drupal/contributed-modules/contrib... →