This module provides support for multilingual blocks

These are not real blocks, but metablocks that group together a number of normal blocks and display the right one depending on language

In the block administration pages you will find a new tab for creating "Multilingual blocks". Set them up as usual and define which one of the other blocks will be shown for each language.

'); case 'admin/build/block/i18n': return t('

These are not real blocks, but metablocks that group together a number of normal blocks and display the right one depending on language

'); } } /** * Implementation of hook_menu() */ function i18nblocks_menu($may_cache) { $items = array(); if($may_cache){ $items[] = array('path' => 'admin/build/block/i18n', 'title' => t('Add multilingual block'), 'access' => user_access('administer blocks'), 'callback' => 'i18nblocks_admin', 'type' => MENU_LOCAL_TASK); } return $items; } /** * Implementation of hook_block() */ function i18nblocks_block($op = 'list', $delta = 0, $edit = array()) { switch($op) { case 'list': $blocks = array(); $result = db_query("SELECT * FROM {i18n_blocks}"); while ($data = db_fetch_object($result)) { $blocks[$data->delta]['info'] = $data->info; } return $blocks; case 'view': return i18nblocks_get_block($delta, i18n_get_lang()); break; case 'configure': return i18nblocks_form(i18nblocks_get_metablock($delta, TRUE), $delta); case 'save': i18nblocks_save($edit, $delta); break; } } /** * Implementation of block form_alter(). * * Remove block title for multilingual blocks. */ function i18nblocks_form_alter($form_id, &$form) { if ($form_id == 'block_admin_configure' && isset($form['block_settings']['i18nblocks'])) { unset($form['block_settings']['title']); $form['block_settings']['title'] = array('#type' => 'value', '#value' => ''); } // Content type setting: Optional nodeasblock synchronization elseif(module_exists('nodeasblock') && $form_id == 'node_type_form' && isset($form['identity']['type'])) { $form['workflow']['nodeasblockset']['i18n_nodeasblock'] = array( '#type' => 'radios', '#title' => t('Create translation blocks automatically'), '#default_value' => variable_get('i18n_nodeasblock_'. $form['#node_type']->type, 0), '#options' => array(0 => t('Disabled'), 1 => t('Enabled')), '#description' => t('Automatic synchronization with blocks generated by nodeasblock module.'), ); } // Node form with nodeasblock settings elseif (isset($form['type']) && ($node = $form['#node']) && $form['type']['#value'] .'_node_form' == $form_id && variable_get("i18n_nodeasblock_$node->type", 0) && isset($form['nodeasblockset'])) { if ($i18nblock = _i18nblocks_nodeasblock($node)) { $block = i18nblocks_get_metablock($i18nblock['delta']); // Override form default values, but not block title foreach( array('block_settings', 'user_vis_settings', 'role_vis_settings','page_vis_settings') as $category) { if (isset($form['nodeasblockset'][$category])) { foreach(element_children($form['nodeasblockset'][$category]) as $field) { if(isset($block->$field) && $field != 'title') { $form['nodeasblockset'][$category][$field]['#default_value'] = $block->$field; } } } } // Override first level value foreach(array('status', 'region', 'weight', 'visibility', 'pages', 'custom') as $field) { if($form['nodeasblockset'][$field]['#type'] == 'value') { $form['nodeasblockset'][$field]['#value'] = $block->$field; } elseif(isset($form['nodeasblockset'][$field]['#default_value'])) { $form['nodeasblockset'][$field]['#default_value'] = $block->$field; } } $form['nodeasblockset']['i18ntxt'] = array('#value' => t('Some block settings have been overridden by the translation block')); } else { // Prepare a new block $i18nblock = array( 'type' => 'nodeasblock', 'info' => '', 'i18nblocks' => array(), 'delta' => '', 'new' => TRUE ); } $form['i18nblock'] = array('#type' => 'value', '#value' => $i18nblock); } } /** * Implementation of hook_nodeapi */ function i18nblocks_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { if (variable_get("nodeasblock_$node->type", 1) && variable_get("i18n_nodeasblock_$node->type", 0)) { switch ($op) { case 'submit': if ($node->i18nblock) { // Copy values from the form before changing any foreach(array('status', 'region', 'weight', 'visibility', 'pages', 'custom', 'info') as $field) { $node->i18nblock['block'][$field] = $node->nodeasblockset[$field]; } // If the block is new, disable the block changing status before it is saved if (!$node->nodeasblock) { $node->nodeasblockset['status'] = 0; $node->nodeasblockset['region'] = BLOCK_REGION_NONE; } } break; case 'update': case 'insert': // Regenerate all translations for this block // This will run after i18n, translations and nodeasblock if(isset($node->i18nblock) && $metablock = $node->i18nblock) { $metablock['nids'][$node->nid] = $node->nid; // Recreate the translation block. Or delete if no blocks. $metablock['i18nblocks'] = array(); $result = db_query("SELECT * FROM {i18n_node} i INNER JOIN {nodeasblock} n ON i.nid = n.nid WHERE i.nid IN (%s) ", implode(',',$metablock['nids'])); while($trn = db_fetch_object($result)) { $metablock['i18nblocks'][$trn->language] = "nodeasblock:$trn->nid"; } if ($metablock['i18nblocks']) { // Set values if new block if(!$metablock['info']) { $metablock['info'] = t('Translation: !title', array('!title' => $node->title)); } $metablock = i18nblocks_save($metablock); // Only if the block is new, rehash block table if (isset($metablock['new'])) { _block_rehash(); } if($block = $metablock['block']) { $block['status'] = 1; $block['delta'] = $metablock['delta']; db_query("UPDATE {blocks} SET status = %d, region = '%s', weight = %d, visibility = %d, pages = '%s', custom = %d WHERE module = 'i18nblocks' AND delta = '%s'", $block['status'], $block['region'], $block['weight'], $block['visibility'], trim($block['pages']), $block['custom'], $block['delta']); } } elseif ($metablock['delta']) { i18nblocks_delete($metablock['delta']); } } break; } } } /** * Helper function: collect translation nids and get related nodeasblock block */ function _i18nblocks_nodeasblock($node) { $nids = $translations = array(); if ($node->trid) { // It is a translation $translations = translation_node_get_translations(array('trid' => $node->trid)); } elseif($node->translation_nid) { // Translation is just being created $translations = translation_node_get_translations(array('nid' => $node->translation_nid), TRUE); $nids[$node->translation_nid] = $node->translation_nid; } foreach($translations as $lang => $trn) { $nids[$trn->nid] = $trn->nid; } if($node->nid) { // Updating existing node, no translations yet $nids[$node->nid] = $node->nid; } // Check for existing block if (!empty($nids) && $i18nblock = db_fetch_array(db_query_range("SELECT m.* FROM {i18n_blocks} m INNER JOIN {i18n_blocks_i18n} b ON m.delta = b.bid WHERE m.type = 'nodeasblock' AND b.delta IN (%s)", implode(',', $nids), 0, 1))) { $i18nblock['nids'] = $nids; return $i18nblock; } } /** * Form for multilingual blocks */ function i18nblocks_form($metablock, $delta = NULL){ $languages = i18n_supported_languages(); $modules = array_intersect(module_list(), module_implements('block')); // Compile list of available blocks $blocklist = array('' => t(' -- ')); foreach (module_implements('block') as $module) { if($module != 'i18nblocks') { // Avoid this module's blocks, could be funny :-) if (is_array($module_blocks = module_invoke($module, 'block', 'list'))) { foreach($module_blocks as $number => $block) { $blocklist[$module.':'.$number] = $block['info']."($module)"; }; } } } $form['info'] = array('#type' => 'textfield', '#title' => t('Block description'), '#default_value' => $metablock->info ? $metablock->info : t('Multilingual block !number', array('!number' => $delta)), '#size' => 40, '#maxlength' => 40 ); $form['type'] = array('#type' => 'value', '#value' => $metablock->type ? $metablock->type : ''); $form['i18nblocks'] = array('#type' => 'fieldset', '#tree' => TRUE, '#title' => t('Select the block to be displayed for each language')); foreach($languages as $lang => $langname){ $block = isset($metablock->blocks[$lang]) ? $metablock->blocks[$lang] :NULL; $form['i18nblocks'][$lang] = array( '#type' => 'select', '#title' => $langname, '#default_value' => $block ? $block->module.':'.$block->delta : '', '#options' => $blocklist ); } // Submit button only for new blocks if($delta) { $form['delete'] = array('#value' => l(t('Delete this block'), 'admin/build/block/i18n/delete/'.$delta)); $form['type'] = array( '#type' => 'radios', '#default_value' => $metablock->type, '#options' => array('' => t('Normal translation block')), '#disabled' => TRUE ); if (module_exists('nodeasblock')) { $form['type']['#options']['nodeasblock'] = t('Node as block with automatic synchronization'); $form['type']['#disabled'] = FALSE; } } else { $form['submit'] = array('#type' => 'submit', '#value' => t('Create block')); } return $form; } /** * Add a new metablock and go to settings page */ function i18nblocks_admin($op = 'add', $delta = NULL, $confirm = FALSE){ if($op == 'add') { $metablock = new StdClass(); $metablock->info = t('New multilingual block'); return drupal_get_form('i18nblocks_form', $metablock); } elseif($op == 'delete' && $delta && $block = i18nblocks_get_metablock($delta)) { i18nblocks_delete($delta); drupal_set_message("The block has been deleted"); drupal_goto('admin/build/block'); } } function i18nblocks_form_submit($form_id, $form_values){ i18nblocks_save($form_values, NULL); return 'admin/build/block'; } /** * Db layer: for now it stores each block as a variable */ function i18nblocks_get_metablock($delta, $getblocks = FALSE){ $metablock = db_fetch_object(db_query("SELECT b.*, i.* FROM {blocks} b INNER JOIN {i18n_blocks} i ON b.delta = i.delta WHERE b.module = 'i18nblocks' AND b.delta = '%s'", $delta)); if ($getblocks) { $result = db_query("SELECT * FROM {i18n_blocks_i18n} WHERE bid = '%s'", $delta); $metablock->blocks = array(); while ($block = db_fetch_object($result)) { $metablock->blocks[$block->language] = $block; } } return $metablock; } // Load and process block data function i18nblocks_get_block($delta, $language){ $meta = db_fetch_object(db_query("SELECT i.*, b.title FROM {i18n_blocks_i18n} i INNER JOIN {blocks} b ON i.delta = b.delta AND i.module = b.module WHERE i.bid = '%d' AND i.language = '%s'", $delta, $language)); if ($block = module_invoke($meta->module, 'block', 'view', $meta->delta)) { if ($meta->title) { // Check plain here to allow module generated titles to keep any markup. $block['subject'] = $meta->title == '' ? '' : check_plain($meta->title); } return $block; } } function i18nblocks_save($edit, $delta = NULL){ $delta = isset($edit['delta']) && $edit['delta'] ? $edit['delta'] : $delta; if ($delta) { db_query("UPDATE {i18n_blocks} SET info = '%s', type = '%s' WHERE delta = '%s'", $edit['info'], $edit['type'], $delta); db_query("DELETE FROM {i18n_blocks_i18n} WHERE bid = %d", $delta); } else { // New block, return delta value $edit['delta'] = $delta = db_next_id('{i18n_blocks}_delta'); if($edit['info'] == t('New multilingual block') || !$edit['info']) { $edit['info'] = t('Multilingual block !number', array('!number' => $delta)); } db_query("INSERT INTO {i18n_blocks}(delta, info, type) VALUES('%d', '%s', '%s')", $delta, $edit['info'], $edit['type']); drupal_set_message(t("Created new block '%name'", array('%name' => $edit['info']))); } // Save language blocks foreach($edit['i18nblocks'] as $lang => $path){ if($path) { list($module, $gamma) = explode(':', $path); db_query("INSERT INTO {i18n_blocks_i18n}(bid, language, module, delta) VALUES(%d, '%s', '%s', '%s')", $delta, $lang, $module, $gamma); } } return $edit; } function i18nblocks_delete($delta) { db_query("DELETE FROM {i18n_blocks} WHERE delta = '%s'", $delta); db_query("DELETE FROM {i18n_blocks_i18n} WHERE bid = '%s'", $delta); }