API перевода Entity
В 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.