Drupal 8 multilingual tidbits 18: core content translation workflow

Up to date as of November 10th, 2015.

In the previous tidbit, we covered content translation basics. In short now you can configure translatability on any subtype of any entity type, so for example articles or specific taxonomy vocabularies may be configured to have all their entities support translation. Then each entity structure may be configured on the field and in some cases subfield level to support translation. The question is how does it all work then, what do we do to translate content?

When can an entity have translations?

When editing an entity, there is a set of conditions to be met for it to have translation support:

  • The bundle (subtype) of the entity should have translation support configured.
  • The site should have more than one configured language.
  • The entity should have a configured language (not one of the "Not applicable" and "Not specified" built-in languages)

There is of course no requirement that the original content entity be of any specific language. Drupal can translate from varying source languages to other target languages.

Example: translate articles

A translate tab would appear on content like this. For example, in this case, I am editing an original Hungarian entity (actual words in English for sake of readers). Behind the translation tab is a list of languages on the site to use as target languages.

At this time, there is no English translation, so I can add one.

The translation form uses the same content editing experience and it even prefills all the original Hungarian field values. In this case, I configured the tags field to not be translatable. A subtle "(all languages)" note appears alongside the tags field. I have access to edit all fields for the translation as a content administrator. (See below for details on permissions).

Once the translation is saved, the content administration list now displays both. It is possible to act on each translation individually to make them published / unpublished (which in my case is per language as is by default). The list may also be filtered by language. What's really great is that this page is a view, so I can customize the content administration experience to support translators better. I can even clone this view/display and create a translation dashboard tab. That would allow me to provide distinct content management and translation management screens.

Other uses of translated content

But where else would the articles show up? Well, the front page is configured by default to show promoted articles in the language selected for the page. So if you view the front page in English, the English translation will show up there. If you view the front page in Hungarian, the Hungarian original will be displayed. Again, the front page is a view, so you can customize how it filters what it shows and what language is used to render the content it finds to display. We covered how views are configured with language options in the blocks and views tidbit.

Finally translated content is also integrated in search. The core search module indexes translations separately. So if you search for "English" in my example, you'll find the English translation immediately. (If your search found no results, make sure to run cron for the indexing to happen. One option is from Administration >> Reports >> Status report). Drupal's search integration APIs are also fully equipped with language information, so third party search integrations will know about translations just as well.

The place and life of translations

Translations exist under their respective original content entities. When editing the original content entity you get buttons to "Save and keep published (this translation)", "Save and unpublish (this translation)", "Preview" and "Delete". In this case "Delete" will remove the entire set of content with all its translations. The confirmation message makes note of that as well.

On the other hand, when editing a translation, the options are a little different. The last one there is "Delete translation" meaning you can delete the translation itself from its parent entity, keeping the parent and all other translations intact. This is possible because a translation is dependent on the "host entity" that it is a translation of. Without that, the translation could not exist. But the translation could be removed without any side effects on the rest of the content.

Drupal also tracks whether each translation is up to date. When editing a translation, one of the sidebar options is to mark all other translations as outdated. When making significant changes to the original content for example, you may want to signal to translators that they need to take a longer look on what to update in their translations. All this does is it puts a flag on the rest of the translations. Translators may filter to this or see this in an overview. When editing a translation, this flag can be unchecked if the translator believes the translation was sufficiently updated.

Permissions around content translation

In the configuration translation tidbit, we covered that there is one single flat permission for translating all of configuration. This is also true for interface translation. However, for content translation, the situation is more difficult. That is because content is created by a much wider audience. In the screenshots above when I created and edited my content translations, I have seen all the fields because I had all permissions on the site.

Content translation module provides a combination of permissions to allow you to configure who has access to edit translations in a much more gragular fashion.

  • The create/edit/delete translations permissions govern whether the respective actions may be done to translations (of some kind). For example, if someone only has permission to edit translations, they will not be able to add new ones or delete existing ones.
  • The create/edit/delete permissions need to be combined with type specific permissions. The overall "Translate any entity" permission gives global permissions to do what was granted of the above three permissions on any entity. For people who should not get that permission, each entity bundle configured to be translatable gets its own permission as well. For example, in my case I configured articles and tags to be translatable, so I get the respective permissions for them.

This way I can configure my proofreaders to only be able to edit translations of articles and tags. If I have legal papers as well, I can restricts their translatability to a more limited group. These permissions do not allow editing non-translatable fields (none of the fields marked with "all languages" would show up for these users). Such shared fields require permission to edit the content itself, because changing them would change the original content as well.

This is the extent of content translation permissions in core. You may agree it is already pretty advanced. However, for example, you cannot limit permissions to specific languages. As with search integration, the content permission system also got expanded in terms of language support, so it is possible to have entity access on a per language fashion as well. Contributed modules will fill in this role.

I hope this summary helped understand the inner workings, features and limitations of the new core content translation features. I think its a really huge step forward for Drupal, especially in the way it applies to all kinds of content entities in core, but is definitely not perfect yet.

In the next tidbit, we will look at some of the content translation API, so you can orient yourself where to look for dealing with content translations. After that I plan to look at complex core use cases where interface, content and configuration translation meet. If you know how the pieces map together, you can really translate practically anything!

Issues to work on


Mike D's picture

I have a custom article content type with a translatable body and a non-translatable "rank" integer[0:255] fields. I've created a view for the items of this content type, filtered by "content translation language = interface text language selected for page" and sorted by "content: rank(asc)". It appears that the view correctly displays both fields in all languages, but orders items by the rank field only in default language. Likewise, the path alias, if declared non-translatable, works only in default language. What am I missing?
Thank you.

Gábor Hojtsy's picture

"Views should not condition joins on the langcode of fields that are not translatable" sounds related. See https://www.drupal.org/node/2451657

David's picture

Hi Gabor,

probably a simple answer, but i cannot find it anywhere. How can entity (node i.e) render fallback disable? I explain better. If i have a site in English & Spanish, and i dont translate node/1, can i config Drupal to avoid es/node/1 to fallback to english version?.

I know how in EntityTranslation in D7 but cannot find anything similar in D8 core.

Thx in advance

Gábor Hojtsy's picture

Global redirect may be the answer or the core issue that would introduce that at https://www.drupal.org/node/2641118. There is no configuration on the user interface to make this happen but a contributed module could so all kinds of fancy things, eg. redirect in this case, or fall back in other ways, etc.

Sandra's picture

Hi Gabor,
I have a blog content type and the registered user has access to translate it. However, the add translation buttons do not appear, only if I enable the "Add translations" permission. In this case a user can translate ALL blogs! How can I limit it to translate only is own content?
Please help! Thank you! Regards

Gábor Hojtsy's picture

Drupal core does not have that granularity in permissions. You would need a contributed module to limit this feature further.

Renaud's picture

Great series of articles, thanks a bunch!

I see it is possible in the advanced search to filter search results based on languages options, nice! Bu is there an option to have normal search results default to the UI language?

In other words, if I search in the French UI with the keyword 'page' the French node Une page de base will be listed in the results BUT NOT the English node A basic page and vice versa ?


Add new comment