logo

Paleta de lienzo: 隆Hazlo colorido!馃帹

Palette - Constructor visual de p谩ginas, no se requiere t铆tulo en dise帽o.

Demo en vivo Descargar Palette

Scroll
18/06/2025, by Ivan

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