How to translate a string from code to content language?

Created on 3 March 2022, about 3 years ago
Updated 8 February 2025, 3 months ago

Problem/Motivation

new TranslatableMarkup("Cookie settings") allows to translate string from code. But as it seems there's no way yet to tell Drupal that this string should be handled by content language, not interface language, if content language is enabled.

Concretely for us the problem exists in hook_menu_links_discovered_alter() where we're defining a dynamic menu entry "Cookie settings" in English.

hook_menu_links_discovered_alter says

title: (required) The title of the menu link. If this should be translated, create a \Drupal\Core\StringTranslation\TranslatableMarkup object.

Using that menu entry on a page with content language (for visitor contents, e.g. in German) and interface language (for admins, e.g. in English) I'd expect the menu entry to be handled as content, not as administration UI (interface). So if I choose German (/de) as content language, it should be German. But it's using the interface language English.

I guess what would be needed is a parameter to TranslatableMarkup() to define in code, that in this case the content language should be used? Or should that be "inherited" from the menu automatically? Or should we need a separate TranslatableContentMarkup()?

Full example from COOKiES module β†’ :

/**
 * Implements hook_menu_links_discovered_alter().
 */
function cookies_menu_links_discovered_alter(&$links) {

  /*
   * Define the "Cookie settings" menu item in Tools.
   * Dynamic equivalent of links.menu.yml entry, but we need to set the URL
   * dynamically because the dialog open fragment can be configured in COOKiES
   * settings.
   *
   * cookies.open_cookie_consent_dialog:
   * title: "Cookie settings"
   * description: "Open the cookie consent dialog."
   * url: "internal:<DYNAMIC:#editCookieSettings>"
   * menu_name: tools
   * options:
   *   attributes:
   *     class:
   *       - cookies-open-cookie-consent-dialog
   */
  $open_settings_hash = \Drupal::config('cookies.config')->get('open_settings_hash');
  if (!empty($open_settings_hash)) {
    $links['cookies.open_cookie_consent_dialog'] = [
      'title' => new TranslatableMarkup("Cookie settings"),
      'description' => new TranslatableMarkup("Open the cookie consent dialog."),
      'url' => "internal:#" .  htmlspecialchars($open_settings_hash, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'),
      'menu_name' => 'tools',
      'provider' => 'cookies',
      'options' => [
        'attributes' => [
          'class' => 'cookies-open-cookie-consent-dialog'
        ]
      ]
    ];
  }
}

Things become even crazier, if a menu can either be an administration menu (interface language) or content menu (content language).

In this specific case, I'd at least expect the menu item to behave like all other menu items - they are using content language! But this one uses interface language.

I created this as support request as I hope I'm doing something wrong here, but it might also be a bug or feature request...

Steps to reproduce

Translate a string which should use content language with new TranslatableMarkup("My english string for content elements") and see it's not possible?

Do we need something like this in core: https://www.drupal.org/project/tranc β†’ ? (We should NOT require to add this as dependency in other modules - it's a core task)
Or should this be solved in the menu module? Or are we doing something wrong?

Proposed resolution

?

Remaining tasks

?

User interface changes

API changes

Data model changes

Release notes snippet

πŸ’¬ Support request
Status

Active

Version

11.0 πŸ”₯

Component

language system

Created by

πŸ‡©πŸ‡ͺGermany Anybody Porta Westfalica

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024