Content Hub

Enhanced language capabilities

Important

Content Hub 2.x will reach end-of-life on December 31, 2024. Acquia recommends that you update your Content Hub version to Content Hub 3.x by using the composer require instructions available on the acquia_contenthub project page.

The acquia_contenthub_translations module extends the capabilities of the current language and translation support. This module syndicates every language and translation to every site in the subscription.

Capabilities and usage

Features

FeatureDescription
Allow selective syndication based on subscribers’ languagesA subscriber with the “es” language attempts to import only “es” translations.
Allow creation of local translationsTranslating content on the subscriber site excludes the content from syndication. The content becomes deletion and update protected from the normal syndication flow.
Allow deletion of translationsUnless the translation is protected, it allows deletion of the translation. By default, translations are not deleted.
Allow update of translationsUpdating a translation makes the content update protected, but not deletion protected.

Usage

The module provides the following configuration options:

OptionDescription
Enable selective language importEnables enhanced capabilities. By default, this option is turned off.
Allow overriding locally modified translationAllows the update of locally modified translations. If an entity is created or modified locally, it becomes deletion and update protected. This configuration overrides this behavior, which means the content follows the normal behavior where it gets updated and/or deleted.

Best practices

Use a unified default language across the subscription

Acquia strongly recommends that you use a singular, unified default language, such as English, to avoid any unexpected behavior due to mixed translations in contents. For single publisher models, the best way to handle multilinguality is to create contents in the English default language to which every subscriber can fall back, if necessary.

Extended workflow

The module attempts to syndicate languages acceptable to a specific subscriber. Therefore, only those translations are syndicated that are enabled on the subscriber. In ideal circumstances, this behavior applies to all cases. However, this behavior does not apply due to certain conditions. For example, when an entity translation references another entity translation in a different language. In that case, the module attempts to resolve the language problem by following the following decision tree. If the subscriber and the to be imported translation do not have a common language between them, the language is enabled and marked as an undesired language.

Undesired languages are the languages that were enabled by necessity because there was no other way to resolve the translation dependency. They are marked so that they do not interfere with the rest of the syndication process. Any further translations incoming within these languages are filtered out.

The following diagram depicts the details of decision making for translation syndication management in the module:

The following table describes the steps mentioned in the diagram:

StepDescription
1Save the entity if the language is not a specified language (und).
2

Save the entity with the configurable language if there is no translation which is amongst the subscriber’s originally enabled languages.

  1. Save the entity with the default language. The rest of the translations are filtered out.
  2. As a result, the configurable language is enabled, opening the door for other translations in the same language. To prevent that behavior, it must be marked as undesired.
  3. Automatically set in configuration to exclude the language from further syndication. Save it only if it is not filterable.
3

Remove filterable languages from the CDF before entity save.

  • Subscriber’s default language
  • First language in line
  • If the accepted language is not the default language of the content, change the default language to one (if there are multiple) of the accepted languages.

Non-translatable entities

Non-translatable entities are handled through special handlers, which are configurable through the config API. The configuration is stored under the following keys:

  • acquia_contenthub_translations.nt_entity_registry.handler_mapping: Holds entity-handler mapping details.
  • acquia_contenthub_translations.nt_entity_registry.unspecified: Holds a list of entities that are unspecified and are not mapped to any of the handlers.

Currently, you can assign the following predefined handlers to an entity type, if needed:

HandlerDescription
unspecifiedThe non-translatable entity has no specific handler, no action will be taken, the entity will be syndicated as it would by the normal syndication flow. If the language of the entity is not present on the subscriber site and the configurable language is part of its dependencies, the language will be imported and enabled.
removableThe non-translatable entity is removable, because we assume that there is a corresponding version of it in a different language. This has to be evaluated individually in order to determine whether this assumption is correct or not.
flexibleThe entity is language flexible, which means it can be recreated on the subscriber site in its own default language.

By default, the module currently handles the following types of entities:

  • path_alias
  • file
  • redirect

Entities that support bundles can be registered with the preceding handlers on a per bundle basis, so that each bundle has an individual handler. In this case, you might want to:

  • Remove a non-translatable node entity of the bundle page
  • Change the language of a non-translatable node entity of the bundle article

You can establish a new mapping by registering a bundle into the handler registry with the following drush eval command:

drush eval '$registry = \Drupal::service("acquia_contenthub_translations.nt_entity_handler.registry");$registry->addEntityToRegistry("entity_type", "bundle", "removable|flexible");'

You can also apply the same handler to all the bundles of a given entity type. In this case, all entities of an entity type are handled with that particular handler:

drush eval '$registry = \Drupal::service("acquia_contenthub_translations.nt_entity_handler.registry");$registry->addEntityToRegistry("entity_type", "entity_type", "removable|flexible");'

If an entity has no specified handler, it is automatically added to the acquia_contenthub_translations.nt_entity_registry.unspecified on entity_type and on a per bundle basis.

To reassign the entity type, the bundle must be first removed from the unspecified list and then added to the handler_mapping list.

Override translatable entities into non-translatable entities

In some cases, Drupal entities are translatable but do not have translations available, such as asymmetric paragraphs or taxonomy terms. Once syndication is complete, these entities may cause incorrect language to display on subscriber sites. To avoid this issue, Acquia recommends adding these entity types to the overridden registry for non-translatable entities.

In this way, any such entity available only in a singular language is added to a removable handler and treated as a non-translatable entity.

This is completed by running a drush eval:

drush eval '$registry = \Drupal::service("acquia_contenthub_translations.nt_entity_handler.registry");$registry->addEntityToOverriddenRegistry("entity_type", "bundle");'

You can also add an entity type without the bundle specificity into the non-translatables overridden registry, which marks that all entities of an entity type will be handled as non-translatable.

drush eval '$registry = \Drupal::service("acquia_contenthub_translations.nt_entity_handler.registry");$registry->addEntityToOverriddenRegistry("entity_type", "entity_type");'

On completion of the drush eval command, add the specified entity type and the bundle to the removable handler:

drush eval '$registry = \Drupal::service("acquia_contenthub_translations.nt_entity_handler.registry");$registry->addEntityToRegistry("entity_type", "bundle", "removable");'

This overrides the behavior of single language entities into non-translatable entities to prune from CDF documents.

Note

The handler registry and the nt-overridden registry both allow adding entities to entity_type:bundle or entity_type:entity_type.

The entity_type:bundle configuration always takes precedence over an entity_type:bundle for a given bundle if both the settings are specified.

Acquia recommends that you register the entities that support bundles on a per bundle specificity rather than a per entity_type specificity.