Problem/Motivation

On multilingual websites, it's common to provide a way to navigate between different language versions of the same piece of content using some kind of menu. Drupal core provides a language switcher block; contrib also provides many alternatives, including drop down menus...

It's also common for content editors, translators, or other localization staff to use this navigation exclusively when adding, editing, or reviewing translations.

There is a bug in the core Content Translation module that breaks this navigation when translated content is created or updated to be in an unpublished state (or, any moderation state other than published in workbench moderation flows). Even though a user has access to view unpublished content, the language switcher links do not link to unpublished content.

Proposed resolution

Core and contrib both rely on the language_negotiation_get_switch_links() function to return a list of links for enabled languages based on the configured/active language negotiation method. The core Content Translation module alters these links because of the way it handles content in different languages (distinct nodes linked together in translations sets by a master nid).

When altering language switch links, the core Content Translation module loads node translations via translation_node_get_translations() and checks the list of language switch links against node translations. If the node translation for a given language is not returned by translation_node_get_translations() or if the node translation exists, but is unpublished, the link is removed, and a "locale-untranslated" class is added.

Because translation_node_get_translations() adds the node_access tag to its db_select() query, the extra check on $node->status by the Content Translation module in translation_language_switch_links_alter() is unnecessary.

Proposed change is to remove the check on $node->status. Existing behavior (of removing language switch links of unpublished content) will be maintained for the originally intended audience (people without access to view unpublished content), while improving navigation for content editors / translators who use the language switch links to navigate through the site.

API changes

Minor: Language switcher links will now include links to unpublished nodes in cases where the current user has permission to view them (e.g. "bypass content access control" or "view own unpublished content," etc. Prior to this change, unpublished nodes would not be linked to, regardless of the current user's permissions to view the content.

These links are used in the core "language switcher" block as well as contributed modules like Language Switcher Dropdown and others.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

iamEAP’s picture

Patch for review. Arguably, if this passes tests, then no tests need to be written.

Tests for this behavior were written in #778528: Define the language switcher's correct behavior for this issue #366768: Translation links link to unpublished translation.

Status: Needs review » Needs work

The last submitted patch, 1: drupal-language_switcher_links_unpublished-2499351-1.patch, failed testing.

iamEAP’s picture

Status: Needs work » Needs review
FileSize
1.65 KB

Ah, so the test essentially read, "Make sure that it's difficult for the translator to get to translated content."

This patch edits the test so that the admin and the translator (who have access to unpublished content) can still see the link, while the anonymous user (who cannot access the unpublished content) does not see the link.

Status: Needs review » Needs work

The last submitted patch, 3: drupal-language_switcher_links_unpublished-2499351-3.patch, failed testing.

iamEAP’s picture

Status: Needs work » Closed (won't fix)

Aaand, never mind. I don't think this is a thing unless you have some kind of content access module installed. I guess I had wild and crazy conceptions about how core handles links/menu items, content access, and unpublished content.

idebr’s picture

@iamEAP You're not crazy. In 7.x it is currently not possible for authors to switch between unpublished node translations.

Currently in translation.module:

function translation_node_get_translations($tnid) {
  if (is_numeric($tnid) && $tnid) {
    $translations = &drupal_static(__FUNCTION__, array());

    if (!isset($translations[$tnid])) {
      $translations[$tnid] = array();
      $result = db_select('node', 'n')
        ->fields('n', array('nid', 'type', 'uid', 'status', 'title', 'language'))
        ->condition('n.tnid', $tnid)
        ->addTag('node_access')
        ->execute();

      foreach ($result as $node) {
        $langcode = entity_language('node', $node);
        $translations[$tnid][$langcode] = $node;
      }
    }
    return $translations[$tnid];
  }
}

Since node access is already checked when loading translations, there is no need to check explicitly for published nodes, so your patch makes sense.