API de traducción de Entidades
En Drupal 8, el idioma de los campos ya no se proporciona en la API pública, en su lugar los campos se adjuntan a objetos con soporte de idioma, de los cuales "heredan" su idioma.
Las principales ventajas aquí son:
- No necesitamos preocuparnos por la portabilidad de los campos, ya que esta la gestiona el objeto entidad internamente.
// Determinar de alguna forma el $active_langcode. $translation = $entity->getTranslation($active_langcode); $value = $translation->field_foo->value;
- Ya no es necesario pasar el idioma activo, de hecho podemos simplemente pasar el objeto de traducción que implementa EntityInterface y es esencialmente un clon del objeto original, solo con un idioma interno diferente. Esto significa que en muchos casos el código recibido puede no conocer el idioma (por supuesto, a menos que explícitamente trate con el idioma).
// Instanciar el objeto de traducción adecuado solo una vez y pasarlo // donde sea necesario. Esto es típicamente manejado por subsistemas del core // y en muchos casos comunes no se requiere recuperar explícitamente // el objeto de traducción. $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; // hacer cosas }
- Ahora tenemos una API reutilizable para la negociación del idioma de la entidad, que se puede usar para determinar la traducción de la entidad que mejor se adapta a un contexto determinado:
// Código simplificado para generar un array renderizable para una entidad. function viewEntity(EntityInterface $entity, $view_mode = 'full', $langcode = NULL) { // El método EntityManagerInterface::getTranslationFromContext() // aplicará la lógica de negociación de idioma de la entidad a todo el objeto // y devolverá el objeto de traducción apropiado para el contexto dado. // El parámetro $langcode es opcional e indica el idioma del contexto actual. // Si no se especifica, se usa el idioma de contenido actual, // que es el comportamiento deseado durante la fase de renderizado. // Tenga en cuenta que los valores de los campos no se modifican, // así que los valores vacíos simplemente no se mostrarán. $langcode = NULL; $translation = $this->entityManager->getTranslationFromContext($entity, $langcode); $build = entity_do_stuff($translation, 'full'); return $build; }
También podemos especificar un parámetro opcional $context, que puede usarse para describir el contexto en el que se usará el objeto de traducción:
// Código simplificado para la generación de reemplazos de tokens. function node_tokens($type, $tokens, array $data = array(), array $options = array()) { $replacements = array(); // Si no se especifica idioma para este contexto, simplemente usamos // el idioma predeterminado de la entidad. if (!isset($options['langcode'])) { $langcode = Language::LANGCODE_DEFAULT; } // Pasamos un parámetro $context que describe la operación que se realiza. // La operación predeterminada es 'entity_view'. $context = array('operation' => 'node_tokens'); $translation = \Drupal::service('entity.repository')->getTranslationFromContext($data['node'], $langcode, $context); $items = $translation->get('body'); // hacer cosas return $replacements; }
La lógica usada para determinar el objeto de traducción devuelto puede ser modificada por módulos. Véase LanguageManager::getFallbackCandidates() para más detalles.
Los datos reales de los campos se distribuyen entre todos los objetos de traducción, y modificar el valor de un campo no traducible lo cambia automáticamente para todos los objetos de traducción.
$entity->langcode->value = 'en'; $translation = $entity->getTranslation('it'); $en_value = $entity->field_foo->value; // $en_value es 'bar' $it_value = $translation->field_foo->value; // $it_value es 'bella' $entity->field_untranslatable->value = 'baz'; $translation->field_untranslatable->value = 'zio'; $value = $entity->field_untranslatable->value; // $value es 'zio'
En cualquier momento se puede crear una instancia de un objeto de traducción desde el objeto original o desde otro objeto de traducción mediante el método EntityInterface::getTranslation(). Si se necesita explícitamente el idioma activo, se puede obtener con EntityInterface::language(). La entidad original puede obtenerse con EntityInterface::getUntranslated().
$entity->langcode->value = 'en'; $translation = $entity->getTranslation('it'); $langcode = $translation->language()->id; // $langcode es 'it'; $untranslated_entity = $translation->getUntranslated(); $langcode = $untranslated_entity->language()->id; // $langcode es 'en'; $identical = $entity === $untranslated_entity; // $identical es TRUE $entity_langcode = $translation->getUntranslated()->language()->id; // $entity_langcode es 'en'
EntityInterface ahora tiene varios métodos que facilitan trabajar con traducciones de entidades. Si un fragmento de código debe actuar sobre cada traducción disponible, puede usar EntityInterface::getTranslationLanguages():
foreach ($entity->getTranslationLanguages() as $langcode => $language) { $translation = $entity->getTranslation($langcode); entity_do_stuff($translation); }
También existen formas de agregar una traducción, eliminarla o comprobar si existe:
if (!$entity->hasTranslation('fr')) { $translation = $entity->addTranslation('fr', array('field_foo' => 'bag')); } // Esto es equivalente al siguiente código, aunque si se especifica un código // de idioma inválido se lanzará una excepción. $translation = $entity->getTranslation('fr'); $translation->field_foo->value = 'bag'; // Acceder a un campo en un objeto de traducción eliminado provoca una excepción. $translation = $entity->getTranslation('it'); $entity->removeTranslation('it'); $value = $translation->field_foo->value; // lanza InvalidArgumentException
Cuando se añaden o eliminan traducciones de entidad al almacenamiento, se disparan respectivamente los siguientes hooks:
- hook_entity_translation_insert()
- hook_entity_translation_delete()
El idioma del campo aún puede obtenerse llamando al método correspondiente del propio objeto campo:
$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.