t('Localizable block'), I18N_BLOCK_METABLOCK => t('Multilingual block (Metablock)'), ); } /** * Implementation of hook_help() */ function i18nblocks_help($section, $arg) { switch ($section) { case 'admin/help#i18nblocks': $output = '

'.t('This module provides support for multilingual blocks.').'

'; $output .= '

'.t('You can set up a language for a block or define it as translatable:').'

'; $output .= ''; $output .= '

' . t('To search and translate strings, use the translation interface pages.', array('@translate-interface' => url('admin/build/translate'))) . '

'; return $output; } } /** * Implementation of hook_db_rewrite_sql() */ function i18nblocks_db_rewrite_sql($query, $primary_table, $primary_key) { global $language; if ($primary_table == 'b' && $primary_key == 'bid') { $return['join'] = 'LEFT JOIN {i18n_blocks} i18n ON b.module = i18n.module AND b.delta = i18n.delta'; $return['where'] = i18n_db_rewrite_where('i18n', 'block', 'simple'); return $return; } } /** * Implementation of hook_block() * * Blocks in i18n_blocks with no language are suppossed to be translatable */ /* function i18nblocks_block($op = 'list', $delta = 0, $edit = array()) { switch($op) { case 'list': $blocks = array(); $result = db_query("SELECT i.*, b.info FROM {i18n_blocks} i INNER JOIN {boxes} b ON i.delta = b.bid WHERE i.module = 'block' AND i.language = ''"); while ($data = db_fetch_object($result)) { $blocks[$data->ibid]['info'] = $data->info . t('[Translatable]'); } return $blocks; case 'view': return i18nblocks_get_block($delta, i18n_get_lang()); break; case 'configure': $form['i18nblocks']['#value'] = t('This is a localizable block'); return $form; } } */ /** * Implementation of hook_locale(). * * This one doesn't need locale refresh because strings are stored from module config form. */ function i18nblocks_locale($op = 'groups', $group = NULL) { switch ($op) { case 'groups': return array('blocks' => t('Blocks')); } } /** * Implementation of block form_alter(). * * Remove block title for multilingual blocks. */ function i18nblocks_form_alter(&$form, $form_state, $form_id) { if (($form_id == 'block_admin_configure' || $form_id == 'block_box_form' || $form_id == 'block_add_block_form')) { $module = $form['module']['#value']; $delta = $form['delta']['#value']; $form['i18n'] = array( '#type' => 'fieldset', '#title' => t('Multilingual settings'), '#collapsible' => TRUE, '#weight' => -1, ); // For i18nblocks, just a help text if ($module == 'i18nblocks') { $form['i18n']['text'] = array('#value' => t('This is a translatable block.')); // Unset block title unset($form['block_settings']['title']); $form['block_settings']['title'] = array('#type' => 'value', '#value' => ''); } else { $i18nblock = i18nblocks_load($module, $delta); $form['i18n'] = array( '#type' => 'fieldset', '#title' => t('Multilingual settings'), '#collapsible' => TRUE, '#weight' => 0, ); // Language options will depend on block type $options = array('' => t('All languages')); if ($module == 'block') { $options[I18N_BLOCK_LOCALIZE] = t('All languages (Translatable)'); } $options += locale_language_list('name'); $form['i18n']['language'] = array( '#type' => 'radios', '#title' => t('Language'), '#default_value' => $i18nblock->language, '#options' => $options, ); // Pass i18ndelta value $form['i18n']['ibid'] = array('#type' => 'value', '#value' => $i18nblock->ibid); $form['#submit'][] = 'i18nblocks_form_submit'; } } } /** * Forms api callback. Submit function */ function i18nblocks_form_submit($form, &$form_state) { $values = $form_state['values']; // Dirty trick to act on new created blocks. Delta may be zero for other modules than block. if (!$values['delta'] && $values['module'] == 'block') { // The last insert id will return a different value in mysql //$values['delta'] = db_last_insert_id('boxes', 'bid'); $values['delta'] = db_result(db_query("SELECT MAX(bid) FROM {boxes}")); } switch ($values['language']) { case I18N_BLOCK_LOCALIZE: // Translatable block $values['language'] = ''; i18nblocks_save($values); break; case '': // No language, delete all i18n information if ($values['ibid']) { db_query("DELETE FROM {i18n_blocks} WHERE ibid = %d", $values['ibid']); } break; default: // The block has a language i18nblocks_save($values); } } /** * Get block language data */ function i18nblocks_load($module, $delta) { $block = db_fetch_object(db_query("SELECT * FROM {i18n_blocks} WHERE module = '%s' AND delta = '%s'", $module, $delta)); // If no result, return default settings if ($block && !$block->language) { $block->language = I18N_BLOCK_LOCALIZE; } return $block ? $block : (object)array('language' => '', 'ibid' => 0); } /** * Set block language data * * @param array $block * Array of block parameters: module, delata, ibid (internal i18nblocks delta) */ function i18nblocks_save($block) { // Update strings for localizable blocks if ($block['ibid']) { db_query("UPDATE {i18n_blocks} SET language = '%s' WHERE ibid = %d", $block['language'], $block['ibid']); } else { db_query("INSERT INTO {i18n_blocks}(module, delta, language) VALUES('%s', '%s', '%s')", $block['module'], $block['delta'], $block['language']); $block['ibid'] = db_last_insert_id('i18n_blocks', 'ibid'); } if (!$block['language']) { $delta = $block['ibid']; tt("blocks:block:$delta:title", $block['title'], NULL, TRUE); tt("blocks:block:$delta:content", $block['body'], NULL, TRUE); } } /** * Load and translate block data * * @param $delta * Block id * @param $language * Language to localize the block */ function i18nblocks_get_block($delta, $language){ // Get block metadata $meta = db_fetch_object(db_query("SELECT b.* FROM {blocks} b INNER JOIN {i18n_blocks} i ON i.delta = b.delta AND i.module = b.module WHERE i.ibid = '%d'", $delta)); // Get block data from module $block = module_invoke($meta->module, 'block', 'view', $meta->delta); if ($block) { // Override the default title if ($meta->title) { // Check plain here to allow module generated titles to keep any markup. $block['subject'] = $meta->title == '' ? '' : check_plain(tt("blocks:block:$delta:title", $meta->title, $language)); } elseif (!empty($block['subject'])) { $block['subject'] = tt("blocks:block:$delta:title", $block['subject'], $language); } $block['content'] = tt("blocks:block:$delta:content", $block['content'], $language); return $block; } } /** * Translate localizable block */ function i18nblocks_translate_block($block) { if ($block->title) { // Check plain here to allow module generated titles to keep any markup. $block->subject = $block->title == '' ? '' : check_plain(tt("blocks:block:$block->delta:title", $block->title)); } elseif (!empty($block->subject)) { $block->subject = tt("blocks:block:$block->delta:title", $block->subject); } $block->content = tt("blocks:block:$block->delta:content", $block->content); return $block; } /** * Implementation of hook_theme() * * This will be used to override the theme_blocks() definition */ function i18nblocks_theme() { return array( 'i18nblocks' => array( 'function' => 'i18nblocks_theme_blocks', 'arguments' => array('region' => NULL), ), ); } /** * Implementation of hook theme_registry_alter() * * Replace theme_blocks with theme_i18nblocks. There may be a better way to do this but * I cannot figure out an easier way to build the whole registry entry * * Warning: this can mess with themes implementing the _blocks function */ function i18nblocks_theme_registry_alter(&$theme_registry) { $theme_registry['blocks'] = $theme_registry['i18nblocks']; } /** * Overrides theme_blocks() and translates blocks on the go */ function i18nblocks_theme_blocks($region) { $output = ''; $i18nmenu = module_exists('i18nmenu'); $i18nblocks = _i18nblocks_list(); if ($list = block_list($region)) { foreach ($list as $key => $block) { // Configurable blocks, may be localizable if ($block->module == 'block') { if (isset($i18nblocks['block'][$block->delta])) { $block = i18nblocks_translate_block($block); } } elseif ($i18nmenu) { // Replace menu blocks by their translated version if ($block->module == 'menu') { $block->content = i18nmenu_translated_tree($block->delta); } elseif ($block->module == 'user' && $block->delta == 1) { $block->content = i18nmenu_translated_tree('navigation'); } } // Finally, render the block using standard theming $output .= theme('block', $block); } } // Add any content assigned to this region through drupal_set_content() calls. $output .= drupal_get_content($region); return $output; } /** * Get list of blocks i18n properties */ function _i18nblocks_list($langcode = '') { static $list = array(); // Handle issues when no $langcode, use a different array index $index = $langcode ? $langcode : I18N_BLOCK_LOCALIZE; if (!isset($list[$index])) { $list[$index] = array(); $result = db_query("SELECT * FROM {i18n_blocks} WHERE language = '%s'", $langcode); while ($info = db_fetch_object($result)) { $list[$index][$info->module][$info->delta] = $info; } } return $list[$index]; }