Drupal 8 multilingual tidbits 20: combination use cases with content and menus

In the previous tidbits we covered each language and translation capability one by one. The community translates the software interface on http://localize.drupal.org/ which you can customize with Interface translation. You can translate your local configuration and content with the Configuration translation and Content translation modules respectively. However, actual real life use cases are never clear cut like that. Content shows up with some shipped interface elements, local configuration and content. Menus contain elements from code, content and configuration. It is good to know how these pieces relate so you can translate every piece and know the right place to do it.

The connection between interface and configuration translation

One of the most common complaints in earlier Drupal core versions is that when you install in a foreign language, if the translation was not complete, later translation updates will not fix untranslated content type names, field names, etc. They are translated with the words available at time of installation. That is because Drupal 7 and before treat configuration as something entered by the administrator on a site. Once it is saved, it is not touched again by the system. Drupal 8 strives to solve this problem by connecting interface translation with configuration translation. This means that configuration that was part of projects (such as Drupal core) when you installed them will be kept updated with translations from interface translation as well. Translations for the site default language (if not English or if English is configured to be translatable) are kept in the active configuration, while other translations are kept as translation overrides.

What does this practically mean? If you are on a translated site and are to use a built-in content type like Article for example, the name, description, title label, etc. for the content type will be managed by both interface translation and configuration translation. If you add a new content type, that will entirely be managed by configuration translation only, given that it was not shipepd with Drupal or a module. Also if you add more fields to the article content type, those will be managed by configuration translation only.

All content created with that content type when output will display a mix of things that are managed by interface translation, configuration translation and content translation. Let's consider this example where I use the article content type and added a region field (Hungary, Europe, etc. to target my content) and a subtitle field:

Of course all the configuration is Hungarian because I installed in Hungarian and created the new fields in Hungarian. All the built-in fields got translations as part of interface translation. The newly added fields are created in Hungarian originally. Drupal 8 is smart enough to handle this situation. Now if I am about to translate this content type configuration to another language, adding French for example on the site would pull in interface translations for the built-in fields in French already and I would only need to manually add translations for the two custom fields.

When seeing these fields on the content editing form, the form will use the language of the page to display the options. For example, the default value configured for the subtitle will show up in the language of the form, the select box will show options in the language of the form. The help text of the select box uses the language of the form. When editing content in Hungarian:

When using the French content translation form, of course all of these will show up in French. It is important to note here that the default value of the subtitle is translated for this input form, but then the subtitle of this content will be independent of original the default value. Once I save this content (even if I keep using the copied default subtitle), the field will be translated with content translation onwards. (On the screenshot I actually changed the field value).

Finally, when the content is display, that uses a mix of configuration and content translation as well. I made the region field a select box, so the actual printed value will depend on the translated configuration for the field (Magyarország in Hungarian and Hongrie in French). That is because the internal value stored is the key for this field (hu), and not the label. For the subtitle field, that is stored as-is in the content, so it will purely use content translation. For the label of the fields though, the configuration translation applies in all cases. I don't think the label would look good on the subtitle, so I removed it, but the region makes sense to lead with a label. All-in-all the French translated version looks like the following:

In this scenario I did not make the region field value translatable, in other words I did not need the Hungarian and French translations to be able to target different regions. If I would need that too, then the resulting translation would depend first on which region key the concrete translation selected, which would then be turned into the proper translated label for the display language of the content based on the field's configuration translation.

That is how interface translation, configuration translation and content translation works together for the translation of a content entity. When it just works, you don't need to care about it, when you set it up, knowing where to look saves you lots of time.

Menus, the black belt master level

If that was a bit complex, consider what a feat it was to make it all work. Also, there is at least one more level up to black belt mastery of translation and that would be menus. Again this is a place where content, configuration and interface translation meet to form interesting combinations.

Let's get shipped menu items out of the way first. Drupal core ships with numerous menu items, the most obvious for translation however is the 'Home' (Címlap in Hungarian) one in the main navigation menu. You'll see that you cannot edit the title or path of this menu item, you can only disable it if you don't want to see it. This menu item is shipped with Drupal as part of the package. That means that it is translated with interface translation.

Imagine I want to add three more menu items to this menu:

  • I want to create a view for my old articles and expose the page under an 'Archive' (Archívum in Hungarian) menu item.
  • I want to create an about us page and expose it as a menu item under the 'About us' (Rólunk in Hungarian) title.
  • I want to have a quick 'Contact us' (Kapcsolat in Hungarian) menu item that leads to the contact form.

All of these end up in my navigation menu. I created them from views, the node form and the menu item user interface respectively. So where are they translated? Well, the same place they are stored. The menu item exposed by views is translatable as part of the view, and the contact link is translated as the custom menu item itself. Custom menu items are content entities in core, so you need to configure content translation is enabled for custom menu items to make it possible to translate them. After that you just have a translate operation on your custom items when editing the menu.

The 'About us' item created from the node form is the most intricate. That is also stored as a content item and requires custom menu items to be translatable the same way the contact link does. However, I entered this on the node form, so I have a natural expectation to translate it there as part of my French translation. Unfortunately the node form's menu widget was not made ready for menu item translations (yet), so if you provide the French menu item title there, it will be updated in the original item and not going to create a translation. Until that is fixed, use the menu item translation process as with the contact menu item.

That allowed me to translate the shipped 'Home' menu item with interface translation, the 'Archive' view menu item with configuration translation and the 'About us' and 'Contact' menu items with content translation. So all is good? Let me show you one more trick.

You may want to display this link at a different place, for example, moving this block into a sidebar block. For better visual separation, we would want to enable displaying the block title for this block. Because I moved this from the header to the sidebar, this is still the block shipped with Drupal core. That means that the block title will already be translated to French, so when switching language, the title shows up properly translated.

However if you are to make another placement of this block in the sidebar instead of moving the menu, that would be a block of your own creation. In that case, while the block title is prefilled by the menu title, it will not be automatically translated (the block's title does not follow the translated menu title dynamically), so you will need to manually translate it to other languages as the block title (with configuration translation of the block placement).

Different menu items for different languages

Now we know all the details of where to translate menu items. But what if we want to add/substract some menu items from our menus for certain languages. Unfortunately that is not possible in Drupal 8 core. However, we can easily create entirely new menus for various languages or language groups. For example, I may want to translate this menu to French (from my Hungarian original) and then create a different menu for German where only 'About us' and 'Contact us' will be present because I am not doing German translation yet.

I can use block visibility settings to limit each block to their respective languages, so the original menu block will only show for French and Hungarian and the new menu's block will only show for German. Then I only need to translate the items in the original menu and can create German items in the specific menu. Later on if I need to adapt this to changing needs, Drupal will know the respective source languages for all items, so I can move to whatever direction I need from there.

In closing

With these directions in mind, I am sure you can figure out even the most puzzling corners of how Drupal 8's multilingual system works. That concludes coverage of the core features and APIs in Drupal 8 for multilingual needs. Next up we'll cover some contributed modules, because yes, however surprising that may be, you may still want to use contributed modules to round out some multilingual features.

Issues to work on

  • The most important of course would be to make the menu widget work properly in content forms, so the right translation may be edited without leaving the node form. https://www.drupal.org/node/2315773 had a grand plan to implement it with fields but unfortunately did not get done.
  • Some configuration elements, while translatable are not exposed on the translation interface. For example the default value for the text field is not. See https://www.drupal.org/node/2546212 for a resolution.

Comments

agoradesign's picture

Szia,
why should we use fields? Sounds like an overkill. I have made a tiny patch, which works great for me. Reviews are very appreciated. https://www.drupal.org/node/2599594

best regards, Andy

Gábor Hojtsy's picture

Indeed, the widget plan was not really to fix this bug but as part of a bigger scheme, eg. to be able to put menu widgets on users or whatever other type of entity. Now that did not happen, fixing the actual bug in a meaningful well contained way is in order. I did not know about this issue, now following :) Thanks a lot for working on it!

agoradesign's picture

Thanks for quick reaction :-) I utilize this momentum to show you another small, yet annoying multilingual issue: https://www.drupal.org/node/2607156

Gábor Hojtsy's picture

Responded.

alex2016's picture

Hi,

thanks for this article.

I don't think your solution for "Different menu items for different languages" using several menus and block visibility really works.
In your example, if we suppose (and I think this is the case) that "Contact us" page shares the same entity id across all languages and if we change the "menu parent" of the node in any languages, it will get changed for the whole entity so for any languages.

Gábor Hojtsy's picture

That was a bug that is fixed in recent releases, see https://www.drupal.org/node/2599594

elia's picture

Hi !
I try to build my website with Drupal 8.
In drupal 7 we can set menu multilingual options:

MULTILINGUAL OPTIONS
Translation mode
- No multilingual options for menu items. Only the menu will be translatable.
- Translate and Localize. Menu items with language will allow translations. Menu items without language will be localized.
- Fixed Language. Menu items will have a global language and they will only show up for pages in that language.
but in drupal 8 it is not available.

There is drop down menu in drupal 8 to choose menu language but i not found its reflect.

how can i in drupal 8 make menu with several items in different languages.
In other words how can i add a menu item in language A without show in language B.

I hope I explained my problem
sorry for my bad English.

Gábor Hojtsy's picture

Drupal 8 does not have such options in core. A contributed module could provide that feature, but I am not aware of any that provides that already. Drupal 8 core only provides the ability to use one menu per language and use block visibility to show/hide them entirely appropriately.

Nehal Rupani's picture

I want to translate same menu item from one menu in multiple language and I want to achieve it with code I am attaching code snippet with my post. I am able to update title of menu but not add new translation with below code.

$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
$menu_links = $menu_link_manager->loadLinksByRoute('entity.node.canonical', array('node' => $nid));

foreach ($menu_links as $menu_link) {
$definition = $menu_link->getPluginDefinition();
$definition['title'] = 'title in hindi';
$definition['langcode'] = 'hi';
$definition['content_translation_source'] = 'en';
$menu_link_manager->updateDefinition($menu_link->getPluginId(), $definition);
}

Gábor Hojtsy's picture

I don't think translated menu items as plugins like you imagine here would work. How would you know which items are of which plugin and if they support translation, etc? Use the content translation system to translate menu items created in core by administrators (or your APIs) in content storage. See http://hojtsy.hu/blog/2015-nov-11/drupal-8-multilingual-tidbits-19-conte... Or use the interface translation system to translate built-in menu items defined in plugin YAML files.

Add new comment