Remixing Drupal the Agaric Way: Multilingual Panels
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!
Comments
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: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.
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
Post new comment