The field_language() function may cause issues when used on node revisions.

To reproduce:

  1. Install a clean Drupal 7 installation ("Standard" profile for fast testing purposes)
  2. Enable the "Locale" & "Content translation" modules
  3. Make sure the body field is translatable (AFAIK - currently the only way to achieve is to manually change the "translatable" value to "1" in the "field_config" table for the "body" field)
  4. Create a new node, of type "Article". Enter a title, but leave the body field empty.
  5. Create a new revision of the node you just created, now enter some content in the body field. Visit the node view. The body field is displayed.
  6. Implement hook_init() in a custom module. Load the first revision of the node you just created & retrieve the languages for it's fields, eg.
    /**
     * Implements hook_init().
     */
    function issue_node_revision_field_language_init() {
      $nid = 1;
      $vid = 1;
      $node = node_load($nid, $vid);
      if ($node) {
        $language = field_language('node', $node);
      }
    }
    
  7. Enable the custom module you just created.
  8. Go back to the node you created. You will see the body content you entered, is not displayed anymore. If you go to the edit form, there is content in it however.

Problem

The root of the problem lies within the field_language() function: https://api.drupal.org/api/drupal/modules%21field%21field.multilingual.i... .
If a field is not set on the entity, the language code of that particular field is set to LANGUAGE_NONE.

In the case of nodes, if working with revisions - there's the possibility that one revision has certain fields not set, while another revision may have it set. In my previous example the first revision doesn't have the body field set, thus get's the language code LANGUAGE_NONE. The second revision however, does have the body field set - and due to the field being translatable, the language code is 'en'.

field_language() puts it's processed results in the static cache, keyed by entity_type/entity_id/entity_language. Because there's no distinction between node revisions, field_language() falsely believes the language code of the body field is LANGUAGE_NONE.

Approaches

Unsure. My first thoughts are manually clearing the &drupal_static('field_language', array()) contents for that particular node, upon displaying a revision?

Comments

rp7’s picture

Issue summary: View changes

Double title.

rp7’s picture

FYI: I discovered this issue using the Workbench Moderation module.

How I currently solved it:

/**
 * Implements hook_entity_prepare_view().
 */
function mymodule_entity_prepare_view($entities, $type, $langcode) {
  // Some fields may not display because field_language() doesn't differentiate
  // between revisions of a node. Clear the functions static cache if we're
  // trying to display a revision of a node which is not the published revision.
  if ($type == 'node') {
    $display_languages = &drupal_static('field_language', array());
    foreach ($entities as $node) {
      if ($node->vid !== $node->workbench_moderation['published']->vid) {
        unset($display_languages[$type][$node->nid]);
      }
    }
  }
}
rp7’s picture

Issue summary: View changes

On display; instead of loading.

recrit’s picture

See #2201251: field_language shouldn't cache display_languages for new entities for a patch that caches by vid and ignores new entities.

Version: 7.23 » 7.x-dev

Core issues are now filed against the dev versions where changes will be made. Document the specific release you are using in your issue comment. More information about choosing a version.