Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Drupal 8 multilingual tidbits 19: content translation development

Parent Feed: 

Up to date as of March 14th, 2017.

Now that we covered how content translation workflow works in Drupal 8, its time to look a bit at the API side. In Drupal 7 this meant dealing with scary seemingly infinitely nested arrays with language codes, field names, deltas, etc. Drupal 8 makes this a whole lot simpler.

Translation basics on an entity

Drupal 8's entity API handles entities as full fledged objects. Translations of entities may be requested from this object and returned as a reusable entity object as well, which can be treated the same way as the original entity that we loaded. Here are some quick examples:

<?php
use Drupal\node\Entity\Node;// Load node 4. In terms of language, this will get us an entity
// in the original submission language.
$node = Node::load(4);// Get a list of all translations and collect titles.
$titles = [];
$languages = $node->getTranslationLanguages();
foreach (
$languages as $langcode => $language) {
// The object returned by getTranslation() behaves the same way as $node.
$translation = $node->getTranslation($langcode);
$titles[$langcode] = $translation->title;
}
// If the node has no Hungarian translation, add one.
if (!$node->hasTranslation('hu')) {
$translation = $node->addTranslation('hu', array('title' => 'Hungarian title'));
$translation->save();
}
// If the node has a Spanish translation, update the title. In case of a missing
// Spanish translation this will throw an InvalidArgumentException.
$node->getTranslation('es')->setTitle('Spanish title')->save();// Remove the Hungarian translation.
$node->removeTranslation('hu');
$node->save();
?>

Loading the right translation

Drupal 8 also comes with several supporting systems for dealing with content language. For example, a content language is selected for the page to be used for translated content display. You can retrieve that language from the language manager and use to deal with the right translation.

<?php
use Drupal\Core\Language\LanguageInterface;
use
Drupal\taxonomy\Entity\Term;$term = Term::load(23);
$langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT->getId());
$translation = $term->getTranslation($langcode);
// Now deal with the right language from here on.
?>

A possible problem with that is getTranslation() will return an exception if the translation requested does not exist. If you want to be sure to load only from existing translations and apply a fallback mechanism for loading suitable translations when something is not available, you need entity language negotiation. That is provided by the entity repository and helps you figure out which translation to load.

<?php
use Drupal\user\Entity\User;$account = User::load(15);
$langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
// Get the user profile with language fallback, if it did not have a translation for $langcode.
$translation = \Drupal::service('entity.repository')->getTranslationFromContext($account, $langcode);
?>

The entity repository uses the language manager and possibly contributed modules to figure out which language to load for the entity. Ideally $langcode would be that language, but if that is not available, modules get a chance to provide fallback schemes for which other language may be best suitable. See LanguageManager::getFallbackCandidates() as well as hook_language_fallback_candidates_alter() and hook_language_fallback_candidates_OPERATION_alter() for more information.

That's it for a short summary of how the much improved content translation API works in Drupal 8. There is of course a lot more to this topic from creating translatable entity types, new field types to dealing with revisions and entity field queries. For some of those deeper details on how content translations are stored and queried, see Francesco Placella's (unfortunately already slightly outdated) articles in Drupal Watchdog titled Wait, $langcode? What the Heck? and Entity Storage, the Drupal 8 Way.

Next up, I plan to look at complex core use cases where interface, content and configuration translation meet. If you know how the pieces map together, you can really translate practically anything!

Issues to work on

None at the moment.

Author: 
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web