3

I have a batch in which i'm importing nodes from REST webservices. My application has two languages, FR and EN (default is FR). So, I'm creating the node in FR, then, I loop through all other languages (just EN for now) and try to do as following :

$languages = \Drupal::languageManager()->getLanguages();
unset($languages['fr']);

foreach ($languages AS $langcode => $language) {
  if ($node->hasTranslation($langcode)) {
    $node_translation = $node->getTranslation($langcode);
  } else {
    $node_translation = $node->addTranslation($langcode, $node->toArray());
  }

  $node_translation->status = 1;
  $node_translation->title = 'title en';
  $node_translation->subtitle = 'subtitle en';
  $node_translation->save();
}

And it crashes with a 500 error, reporting :

 - Drupal\Core\Entity\EntityStorageException : Invalid translation language (und) specified. dans Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (ligne 805 de /.../web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).
 - InvalidArgumentException : Invalid translation language (und) specified. dans Drupal\Core\Entity\ContentEntityBase->getTranslation() (ligne 783 de /.../web/core/lib/Drupal/Core/Entity/ContentEntityBase.php).

I'm pulling my hair out on this issue for days and can not understand why the error message tells me $langcode equals 'und' whereas a var_dump of it just before this line returns me 'en'.


Edit : I tried to hardcode and remove the foreach. So just after the $node->save() :

$node_translation = $node->addTranslation('en', $node->toArray());
$node_translation->set('title', 'title en');
$node_translation->set('field_sub_title', 'subtitle en');
$node_translation->save();

This time, the error is the following :

InvalidArgumentException : Invalid translation language (en) specified.
dans Drupal\Core\Entity\ContentEntityBase->addTranslation() (ligne 863
de /var/www/drupalvm/drupal/web/core/lib/Drupal/Core/Entity/ContentEntityBase.php).
  • I tried the solutions given in this post, but it won't work drupal.stackexchange.com/questions/203149/… – Pauloscorps Feb 1 '18 at 16:47
  • If you run $node->language() before the foreach what does it contain? – johndevman Feb 5 '18 at 13:45
  • protected 'name' => string 'French' (length=6) protected 'id' => string 'fr' (length=2) protected 'direction' => string 'ltr' (length=3) protected 'weight' => int 1 protected 'locked' => boolean false – Pauloscorps Feb 5 '18 at 16:03
3

After several days, I finally found the solution. Obviously, there is a bug with Drupal (here 8.4.0).

The hasTranslation() method don't work properly. Instead, you should use EntityManager::getTranslationFromContext() (will be deprecated in Drupal 9 though).

You can also write a new method like this one to replace it:

/**
 * Check if a node as a translation for the given language.
 *
 * @param object $node
 *   The node object.
 * @param string $langcode
 *   The langcode.
 *
 * @return bool
 *   True (exists) or false (does not exist).
 */
function has_translation($node, $langcode) {
  $existing_translation = \Drupal::service('entity.repository')->getTranslationFromContext($node, $langcode);
  return ($existing_translation->langcode->value === $langcode) ? TRUE : FALSE;
}

So, my corrected code is the following:

if (has_translation($node, $langcode)) {
  $node_translation = $node->getTranslation($langcode);
  $node_translation->title = 'title en';
  $node_translation->field_sub_title = 'subtitle en';
  $node_translation->status = NodeInterface::PUBLISHED;
}
else {
  $node->addTranslation($langcode, $values);
}

$node->save();
0

You can try with simple code:

$node = Node::load(1);
if (!$node->hasTranslation('en')) {
    $translation = $node->addTranslation('en', $node->toArray());
    $node->save();
}

You can't translate just because you wrong target. You need to know original language.

  • That's exactly what I'm doing after the foreach opens. – Pauloscorps Feb 6 '18 at 8:15
  • See in your code, try $node->save() don't $node_translation->save() – MrD Feb 6 '18 at 8:20
  • Oh, sorry, I didn't get it. Does not work by the way, always the "invalid translation language (en)" exception. – Pauloscorps Feb 6 '18 at 8:29
  • Just snippet code help you can translate a note. You can add to loop language and translate theme. See more example api.drupal.org/api/drupal/… – MrD Feb 6 '18 at 8:46
0

No code needed, you can use Lingotek Module and trigger by rules module on new node save and or updated, condition: check in what language is uploaded so you can create another node in the second language. be carefull with google, it will penalize you if you index both nodes, to take care of this you can use No index module or something similar. I made a site with all of above and works perfect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.