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