I'm currently contemplating Entity Translation integration for Inline Entity Form.

The idea of IEF is that you manage referenced entities right there on the parent entity form.
Let's assume a use case of a node referencing commerce products.
So:
1) if you're editing an english node, newly added products also have "english" set as their language.
2) If you're using Entity Translation and adding a french translation for the node, then the product values should be saved under "fr" as well.
(Assuming ET is enabled for both entity types).

So, looking at the ET codebase briefly told me that I should instantiate a translation handler for the inline entity form (which will then handle the tricky parts for me, such as changing the source language). However, ET doesn't use #parents to store the translation handler in form state, which means there can be only one. Hence this request to allow multiple.
Alternatively, please suggest how I should proceed in regards to this matter.

Thanks!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

plach’s picture

Well, coupling the translation handler with $form_state was initially a quick and dirty addition to deal with AJAX calls that do not involve going through the usual entity edit routes, which among the rest are responsible to set the current form language (see entity_translation_edit_page()). I think a more consistent work on this using #parents would be welcome, but I'd need to see a patch to be sure.

candelas’s picture

any news on this? we need a way for products variations to get translated...
thanks for your excellent work :)

plach’s picture

Status: Active » Needs review
FileSize
42.32 KB
33.26 KB

I spent the last days working on the integration between ET and IEF (a tough task, btw). The attached patch should enable IEF to integrate with ET. The goal of the patch was to decouple the translation handler from the form state and just store there the need contextual information, that is the current form and source languages. This allows to instantiate a translation handler in any point of the execution flow through a centralized (singleton) factory, which is the sole responsible for ensuring we have just one translation handler instance for each entity. In turn this avoids losing the contextual information after restoring it from the form state (this is mainly needed when proessing AJAX requests, as pointed out in #1).

The patch supports nested entity forms by cleaning up some assumptions in the entity form massaging and (most importantly) by allowing to register child translation handlers: when the root translation handler contextual information is updated all the children are updated accordingly. This should allow us to support arbitrarily nested entity forms (actually I didn't tested that, just a single nesting level :).

The attached patch includes the #1947764: Improve bundle translatability checks API clean-up, which willl be committed soon. There is also an interdiff for reviewers' convenience.

Disclaimer: this has the potential to break lots of stuff (although it performs many clean-ups that simplify the current code), hence it needs to be carefully tested before commit.

plach’s picture

+++ b/entity_translation.module
@@ -1413,16 +1433,22 @@ function entity_translation_entity_form_validate($form, &$form_state) {
+  // Ensure the handler form and source languages match the actual ones. This is
+  // mainly needed when responding to an AJAX request where the languages cannot

This comment should mention only the form language.

+++ b/includes/translation.handler.inc
@@ -15,6 +15,16 @@
+  /**
+   * Registers a child translation handler for the given entity.
+   */

We should probably have also a method to remove the child.

+++ b/includes/translation.handler.inc
@@ -1213,17 +1279,14 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
+    $form = array(
+      'entity_translation_entity_form_language_update' => array(
+        '#element_validate' => array('entity_translation_entity_form_language_update'),
+        '#entity_type' => $this->entityType,
+       ),

An array_unshift would probably be more efficient here.

plach’s picture

plach’s picture

+++ b/includes/translation.handler_factory.inc
@@ -0,0 +1,131 @@
+    return isset($this->lastByType[$entity_type]) ? $this->lastByType[$entity_type] : $this->last;

$this->last should be returned only if $entity_type is empty.

plach’s picture

Rerolled after the latest commits and addressed the minor issues above.

klonos’s picture

bforchhammer’s picture

Note, patch #7 seems to fix an EntityMalformedException which occurs when adding taxonomy terms on the node page; see #2008366: EntityMalformedException when adding new tags to taxonomy.

bforchhammer’s picture

#7: et-form_handlers-1865244-7.patch queued for re-testing.

Requesting tests again, because previous run didn't include menu tests (plus we've had a few bug fixes since the patch was added).

ciss’s picture

#7: et-form_handlers-1865244-7.patch queued for re-testing.

candelas’s picture

any news? thanks :)

candelas’s picture

i downloaded the dev version and applied the patch #7 because i was getting the EntityMalformedException when adding new tags to taxonomy in a blog on Commerce Kickstart distribution.

now when i try to translate a blog new i have the problem that i cant translate. sorry for my bad english. i try to explain my best:

i have english and spanish languages.
i make a english new.
i save it (button with save and translate disappeared)
i go to translate and i see that spanish it is not done.
i ask to translate but i get edit instead. there are not the 2 buttons on top right with both languages and i can choose the language from a select.
i choose the spanish language from the select and then save.
what it makes is that it changes the original language, instead of making a new translation.

if you have any doubt about my explanation, please, tell to me and i try to explain again.

thanks a lot for your work :)

csedax90’s picture

Priority: Normal » Critical

same problem, the patch doesn't solved the issue

bojanz’s picture

Priority: Critical » Normal

This is a refactoring, it's not meant to solve any Kickstart issues directly.

plach’s picture

Priority: Normal » Major
FileSize
33.91 KB

Rerolled after the latest commits.

@candelas:

Did you run the updates and clear the cache after applying the patch?

plach’s picture

Assigned: Unassigned » plach
FileSize
36.69 KB

Tested the attached patch with #1344672: Field Collection: Field translation (entity_translation) support. and it seems to be working well. I will commit it soon.

candelas’s picture

thanks very much @plach for so much hard work. i am finishing a work and i will be able to test next week :)

agoradesign’s picture

Status: Needs review » Needs work

I've found something very important:

The patch uses the following command 5 times:

<?php
$this->notifyChildren(__FUNCTION__, func_get_args());
?>

Well, unfortunately this breaks PHP 5.2 compatiblity, as you cannot call func_get_args() directly as function parameter. You have to first store the result in a variable and use that as parameter. Similar (older) core issue incl. fix: https://drupal.org/node/1411592

plach’s picture

Thanks for reporting, would the following alternative work?

<?php
$this->notifyChildren(__FUNCTION__, $args = func_get_args());
?>
agoradesign’s picture

No, just tried it. But when I try to create a new node, I still get the same error:

Fatal error: func_get_args(): Can't be used as a function parameter in /drupal/sites/all/modules/entity_translation/includes/translation.handler.inc on line 1026

Seems that there's no way around doing it like this:

<?php
    $args = func_get_args();
    $this->notifyChildren(__FUNCTION__, $args);
?>
plach’s picture

Weird, they should be totally equivalent. Are you sure you replaced all occurrences?

agoradesign’s picture

Yes, I'm sure. In fact, before I tried your approach, I had already replaced all 5 occurrences with the two-line variant to fix it. Starting from that working code base I've changed it to your approach, and it stopped working, giving me the error message above.

From php.net:

Because this function depends on the current scope to determine parameter details, it cannot be used as a function parameter in versions prior to 5.3.0. If this value must be passed, the results should be assigned to a variable, and that variable should be passed.

http://www.php.net/manual/en/function.func-get-args.php

ciss’s picture

Unfortunately agoradesign is right. The problem seems to be caused by the way PHP tries to determine the current scope. Fun fact: It will work if func_get_args() gets called as the first argument.

You can try this yourself on sandbox.onlinephpfunctions.com choosing the right PHP version.
Unfortunately their sharing feature is currently broken, so here's the code I used:

class Test {
  public function run($arg1, $arg2) {
    $this->fgaFirst(func_get_args(), __METHOD__);
    $this->fgaLast(__METHOD__, func_get_args());
  }

  protected function fgaFirst($args, $method) {
    print_r(array('method' => $method, 'args' => $args));
  }

  protected function fgaLast($method, $args) {
    print_r(array('method' => $method, 'args' => $args));
  }
}

$t = new Test;
$t->run(1, 2);
plach’s picture

@ciss:

Thanks for the additional background :)

I think reversing the arguments is not good for DX so I guess will just have to bite the bullet and go with #21. I'll provide a new patch ASAP.

plach’s picture

Status: Needs work » Needs review
FileSize
1.75 KB
36.79 KB

Here it is.

interdruper’s picture

After the patch #26, I get this error:

Strict warning: Only variables should be passed by reference en EntityTranslationHandlerFactory->getHandler() (line 79 of entity_translation\includes\translation.handler_factory.inc).

agoradesign’s picture

Seems to be a similiar problem. Line 79 is:

<?php
$entity = reset(entity_load($entity_type, array($entity)));
?>

The return value of entity_load() should be stored in a variable first to avoid the PHP warning

plach’s picture

bojanz’s picture

Question: Will something like this need to be done in D8 core, or does that API already support translating two entities on the same form?

plach’s picture

In D8 we have entity forms that natively support form language and a proper Entity Translation API, so the translation controller is way thinner and has only the reposibility of massaging the form. I don't think we will need anything like this.

However there's an issue to ensure entity forms can be nested: #1728816: Ensure multiple entity forms can be embedded into one form.

joel_osc’s picture

Thanks for the patch, this is great work. I did notice one thing now with patch, when I go to add a translation the fields which are not translable are showing even though I have entity_translation configured to hide them.

plach’s picture

Status: Needs review » Reviewed & tested by the community

Sorry, I cannot replicate #32: I will commit this in a couple of days, if you can reproduce the problem on a clean installation please post the steps before commit, otherwise we will open a follow-up. We need a wider testing audience here.

joel_osc’s picture

Sounds like a good plan - I have numerous patches on my system so it could be just something I induced locally.

das-peter’s picture

@plach I totally agree with #33 since this seems to solve #1925848: Pathauto generates language neutral alias on node creation too.

klonos’s picture

Yeah, #1344672: Field Collection: Field translation (entity_translation) support. seems to need it to move forward too. So, lets just commit and see if there are still issues. In that case, we can file separate follow-up issues.

plach’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed, thanks everyone for testing. If you find related issues, please link them here.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

plusproduit’s picture

Hello,

I reopen this issue, because there seems to be a problem when you update a vocabulary with ET translated terms, here's how to replicate:

  1. Get your aliases working, and bulk update
  2. Edit the vocabulary and save
  3. You get a success message: Reset language for all terms, Updated vocabulary XXX.
  4. Delete and bulk generate aliases: Language is set to all
  5. To repair this, you have to edit your terms in original language, check automatic alias and save

That's not an option with a 100+ terms vocabulary, any ideas ?
Thanks

klonos’s picture

Please open a new issue. Thanx.

  • Commit d53a9a3 on 7.x-1.x, et-fc, revisions by plach:
    Issue #1865244 by plach | bojanz, agoradesign, ciss, interdruper,...

  • Commit d53a9a3 on 7.x-1.x, et-fc, revisions, workbench by plach:
    Issue #1865244 by plach | bojanz, agoradesign, ciss, interdruper,...
pbuyle’s picture

Issue summary: View changes

In #2285355: Translations of the parent entity are lost when creating a child entity with an Inline entity form, I've got an issue. I've two translation handlers on the same form. They both add a language selector to the form, with the same key. So the second handler ends up overriding the first handler's language selector.

plach’s picture