Remixing Drupal the Agaric Way: Multilingual Panels

By Benjamin Melançon
on 22 Nov
2 comments

Key words and phrases

i18n moddule panels i18n agaric

Tags

Description

Step 1: Find a function that does some or most of what you want.
Step 2: Find another function that does the rest of what you want.
Step 3: Mash them together.

The situation this time: we have a Drupal 5 site (World Social Forum 2008) with i18n (internationalization module) and need translated content to show up in panels.

Update: Go straight to the patch.

Here's some code in translation.module of the i18n package that shows one way this translation system for multilingual Drupal 5 figures out what nodes to care about:

<pre>
/**
* Implementation of hook_link().
*/
function translation_link($type, $node = NULL, $teaser = FALSE) {
  $languages = i18n_supported_languages();
  $links = array();
  if ($type == 'node' && variable_get('i18n_translation_node_links', 0) > ($teaser ? 1 : 0) && $node->translation) {
    foreach ($node->translation as $lang => $trnode) {
      // Add node link if published
      if($trnode->status) {
        // If language is not enabled, we'll use current language for the prefix
        $baselang = variable_get('i18n_translation_links', 0) || !isset($languages[$lang]) ? i18n_get_lang() : $lang;
        $links['translation-'.$lang]= theme('translation_node_link', $trnode , $lang, $baselang);
      }
    }
  }
  return $links;
}
</pre>

And here is the code from node.inc of the Panels package, which provides all the basic information for showing nodes:

<pre>/**
* Output function for the 'node' content type. Outputs a node
* based on the nid and settings supplied in the configuration.
*/
function panels_content_node($conf) {
  $node = node_load($conf['nid']);
  if (!node_access('view', $node)) {
    return;
  }

  if ($conf['suppress_title']) {
    $node->title = '';
  }

  $output = node_view($node, $conf['teaser'], FALSE, $conf['links']);
  return $output;
}</pre>

(Note: I've already changed the comment text above this function, which in the original was clearly a copy of the block.inc text.)

So let's mix and match, making the panels node view function multilingual-compatible with the parts Agaric added in bold:

<pre>
function panels_content_node($conf) {
  $node = node_load($conf['nid']);
  if (!node_access('view', $node)) {
    return;
  }
<strong>
  /* this could be optimized to check for translations by nid
   * BEFORE the node is loaded above.  This is a lot easier though.
   * Maybe not a big deal with node caching?
   */
  if ($node->translation) {
    // i18n_get_lang() gets the language the site is being browsed in
    if (array_key_exists(i18n_get_lang(), $node->translation)) {
      $lang = i18n_get_lang();
    } else {
      // use the default language
      $lang = i18n_default_language();
    }
    // avoid redundant node load, even if cached
    if ($node->language != $lang) { 
      $node = node_load($node->translation[$lang]->nid);
    }
  }
</strong>
  if ($conf['suppress_title']) {
    $node->title = '';
  }

  $output = node_view($node, $conf['teaser'], FALSE, $conf['links']);
  return $output;
}
</pre>

Agaric is pretty sure you aren't consigned to hell for hacking Drupal contrib modules. Only a few years in purgatory. This would have been better done with creating another include file to provide a separate interface for translated nodes, but this has very little performance impact if the node doesn't have a translation-- and Views 2 plus Drupal 6 had better just do it!

 

In addition to forgetting

In addition to forgetting the obligatory parenthesis for the first if () statement, and a semicolon in the last one, I neglected to put on the final array key [EDIT: not array, but an object '->'] in $node = node_load($node->translation[$lang]) (even though I had mentally noted I had to. ADHD is not for the complacent coder).

This had the entirely irrelevant (but interesting) side effect of showing me what node_load tries to do when handed an array with extra keys:

SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE n.nid = '%s' AND n.title = '%s' AND n.status = '%s' AND n.language = '%s',
Array
(
[0] => 568
[1] => Italian title
[2] => 1
[3] => it
)

What was actually passed in:

[it] => stdClass Object (
 [nid] => 568
 [title] => Italian title
 [status] => 1 
 [language] => it
)

This gave an error of course since there is no such thing as n.language (Agaric is just ahead of our time, something like it exists in Drupal 6). But still-- pretty interesting, that.

Posted by Benjamin Melançon on Thu, 2007-11-22 06:53
Thanks

Hey mate,

Thanks a lot for this code. I used it in Panels2, except instead of putting it in the Node content type, I put it straight in the context, so that all related panes will see the translated node.

Peace

Pawel

Posted by PawelPohl (not verified) on Thu, 2008-06-12 01:33
Post new comment
The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <h1> <h2> <h3> <h4> <h5> <h6> <small> <pre> <strike> <sub> <sup> <kbd> <s>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.