Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll
20/05/2020, by maria

В Drupal 8 язык полей больше не предоставляется в общедоступном API, вместо этого поля присоединяются к объектам с поддержкой языка, от которых они «наследуют» свой язык.

Основными преимуществами здесь являются:

  • Нам не нужно беспокоиться о переносимости полей, так как об этом заботится объект сущности внутри.
      // Determine the $active_langcode somehow.
      $translation = $entity->getTranslation($active_langcode);
      $value = $translation->field_foo->value;
  • Нам больше не нужно передавать активный язык, фактически мы можем просто передать объект перевода, который реализует EntityInterface и фактически является клоном исходного объекта, просто с другим внутренним языком. Это означает, что во многих случаях полученный код может не знать язык (конечно, если он явно не имеет отношения к языку).
      // Instantiate the proper translation object just once and pass it around
      // wherever it is needed. This is typically taken care of by core
      // subsystems and in many common cases an explicit retrieval of the
      // translation object is not needed.
      $langcode = Drupal::languageManager()->getLanguage(Language::TYPE_CONTENT);
      $translation = $entity->getTranslation($langcode);
      entity_do_stuff($translation);

      function entity_do_stuff(EntityInterface $entity) {
        $value = $entity->field_foo->value;
        // do stuff
      }
    
  • Теперь у нас есть повторно используемый API согласования на языке entity, который можно использовать для определения перевода сущности, который наиболее подходит для определенного контекста:
      // Simplified code to generate a renderable array for an entity.
      function viewEntity(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) {
        // The EntityManagerInterface::getTranslationFromContext() method will
        // apply entity language negotiation logic to the whole entity object
        // and will return the proper translation object for the given context.
        // The $langcode parameter is optional and indicates the language of the
        // current context. If it is not specified the current content language
        // is used, which is the desired behavior during the rendering phase.
        // Note that field values are left alone in the process, so empty values
        // will just not be displayed.
        $langcode = NULL;
        $translation = $this->entityManager->getTranslationFromContext($entity, $langcode);
        $build = entity_do_stuff($translation, 'full');
        return $build;
      }
    

Мы также можем указать необязательный параметр $context, который можно использовать для описания контекста, в котором будет использоваться объект перевода:

      // Simplified token replacements generation code.
      function node_tokens($type, $tokens, array $data = array(), array $options = array()) {
        $replacements = array();

        // If no language is specified for this context we just default to the
        // default entity language.
        if (!isset($options['langcode'])) {
          $langcode = Language::LANGCODE_DEFAULT;
        }

        // We pass a $context parameter describing the operation being performed.
        // The default operation is 'entity_view'.
        $context = array('operation' => 'node_tokens');
        $translation = \Drupal::service('entity.repository')->getTranslationFromContext($data['node'], $langcode, $context);
        $items = $translation->get('body');

        // do stuff

        return $replacements;
      }
   

Логика, используемая для определения возвращаемого объекта перевода, может изменяться модулями. См. LanguageManager :getFallbackCandidates() для более подробной информации.

Фактические данные поля распределяются между всеми объектами перевода, и изменение значения непереводимого поля автоматически изменяет его для всех объектов перевода.

  $entity->langcode->value = 'en';
  $translation = $entity->getTranslation('it');
  
  $en_value = $entity->field_foo->value; // $en_value is 'bar'
  $it_value = $translation->field_foo->value; // $it_value is 'bella'

  $entity->field_untranslatable->value = 'baz';
  $translation->field_untranslatable->value = 'zio';
  $value = $entity->field_untranslatable->value; // $value is 'zio'

В любой момент можно создать экземпляр объекта перевода из исходного объекта или другого объекта перевода с помощью метода EntityInterface::getTranslation(). Если активный язык явно необходим, его можно получить через EntityInterface::language(). Исходная сущность может быть получена через EntityInterface::getUntranslated().

  $entity->langcode->value = 'en';

  $translation = $entity->getTranslation('it');
  $langcode = $translation->language()->id; // $langcode is 'it';

  $untranslated_entity = $translation->getUntranslated();
  $langcode = $untranslated_entity->language()->id; // $langcode is 'en';

  $identical = $entity === $untranslated_entity; // $identical is TRUE

  $entity_langcode = $translation->getUntranslated()->language()->id; // $entity_langcode is 'en'

EntityInterface теперь имеет несколько методов, которые облегчают работу с переводами сущностей. Если фрагмент кода должен действовать для каждого доступного перевода, он может использовать EntityInterface::getTranslationLanguages():

  foreach ($entity->getTranslationLanguages() as $langcode => $language) {
    $translation = $entity->getTranslation($langcode);
    entity_do_stuff($translation);
  }

Существуют также способы добавить перевод, удалить его или проверить его наличие:

  if (!$entity->hasTranslation('fr')) {
    $translation = $entity->addTranslation('fr', array('field_foo' => 'bag'));
  }

  // Which is equivalent to the following code, although if an invalid language
  // code is specified an exception is thrown.
  $translation = $entity->getTranslation('fr');
  $translation->field_foo->value = 'bag';

  // Accessing a field on a removed translation object causes an exception to
  // be thrown.
  $translation = $entity->getTranslation('it');
  $entity->removeTranslation('it');
  $value = $translation->field_foo->value; // throws InvalidArgumentException

Когда переводы entity добавляются в хранилище или удаляются из него, соответственно запускаются следующие ловушки:

  • hook_entity_translation_insert()
  • hook_entity_translation_delete()

Язык поля все еще можно получить, вызвав соответствующий метод для самого объекта поля:

  $langcode = $translation->field_foo->getLangcode();

 

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.