logo

Paleta - Deixe colorido🎨

Palette — Construtor visual de páginas. Não precisa ser designer.

Demonstração ao vivo Baixar Palette

Scroll

API de tradução de entidades

20/05/2020, by maria

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

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

  • Нам не нужно беспокоиться о переносимости полей, так как об этом заботится объект сущности внутри.
      // Determine the $active_langcode somehow.
      $translation = $entity->getTranslation($active_langcode);
      $value = $translation->field_foo->value;
  • Não precisamos mais passar o idioma ativo — na prática podemos simplesmente passar o objeto de tradução, que implementa EntityInterface e é na verdade um clone do objeto original, apenas com idioma interno diferente. Isso significa que em muitos casos o código receptor pode nem saber do idioma (claro, se ele não tratar explicitamente de idioma).
      // 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
      }
  • Temos agora uma API reutilizável de negociação de idioma da entidade, utilizável para determinar qual tradução da entidade é mais adequada para um contexto específico:
      // 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;
      }

Podemos também indicar o parâmetro opcional $context, usado para descrever o contexto no qual o objeto de tradução será utilizado:

      // 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'

A qualquer momento pode-se instanciar um objeto de tradução a partir do objeto original ou de outro objeto de tradução pelo método EntityInterface::getTranslation(). Se o idioma ativo for explicitamente necessário, obtém-se via EntityInterface::language(). A entidade original obtém-se por 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'

A EntityInterface agora tem vários métodos que facilitam trabalhar com traduções de entidades. Se um trecho de código deve agir sobre cada tradução disponível, pode usar EntityInterface::getTranslationLanguages():

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

Há também formas de adicionar uma tradução, removê-la ou verificar sua existência:

  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();