4f0fa0362e4789a7423197e1f576707677e3b2af
5 * Internationalization (i18n) submodule: Multilingual meta-blocks
7 * @author Jose A. Reyero, 2005
9 * @ TODO Add strings on block update
12 // Tag for localizable block, cannot be any language
13 define('I18N_BLOCK_LOCALIZE', '__LOCALIZE__');
16 * Implementation of hook_help()
18 function i18nblocks_help($section = 'admin/help#i18nblocks' ) {
20 case
'admin/help#i18nblocks':
21 return t('<h2>This module provides support for multilingual blocks</h2>
22 <p>These are not real blocks, but metablocks that group together a number of normal blocks and display the right one depending on language</p>
23 <p>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.</p>
25 case
'admin/build/block/i18n':
26 return t('<p>These are not real blocks, but metablocks that group together a number of normal blocks and display the right one depending on language</p>');
31 * Implementation of hook_db_rewrite_sql()
33 function i18nblocks_db_rewrite_sql($query, $primary_table, $primary_key) {
35 if ($primary_table == 'b' && $primary_key == 'bid') {
36 $return['join'] = 'LEFT JOIN {i18n_blocks_language} i18n ON b.module = i18n.module AND b.delta = i18n.delta';
37 $return['where'] = i18n_db_rewrite_where('i18n', 'block', 'simple');
42 * Implementation of hook_menu()
45 function i18nblocks_menu() {
46 $items[] = array('path' => 'admin/build/block/i18n', 'title' => t('Add multilingual block'),
47 'access' => user_access('administer blocks'),
48 'callback' => 'i18nblocks_admin',
49 'type' => MENU_LOCAL_TASK);
54 * Implementation of hook_block()
56 function i18nblocks_block($op = 'list', $delta = 0, $edit = array()) {
60 $result = db_query("SELECT * FROM {i18n_blocks}");
61 while ($data = db_fetch_object($result)) {
62 $blocks[$data->i18ndelta
]['info'] = $data->info
;
66 return i18nblocks_get_block($delta, i18n_get_lang());
69 //return i18nblocks_form(i18nblocks_get_metablock($delta, TRUE), $delta);
72 //i18nblocks_save($edit, $delta);
78 * Implementation of hook_locale().
80 function i18nblocks_locale($op = 'groups') {
83 return array('blocks' => t('Blocks'));
88 * Implementation of block form_alter().
90 * Remove block title for multilingual blocks.
92 function i18nblocks_form_alter(&$form, $form_state, $form_id) {
93 if ($form_id == 'block_admin_configure') {
94 $form['i18n'] = array(
95 '#type' => 'fieldset',
96 '#title' => t('Multilingual settings'),
97 '#collapsible' => TRUE
,
99 // For i18nblocks, just a help text
100 if (($module = $form['module']['#value']) == 'i18nblocks') {
101 $form['i18n']['text'] = array('#value' => t('This is a translatable block.'));
103 unset($form['block_settings']['title']);
104 $form['block_settings']['title'] = array('#type' => 'value', '#value' => '');
106 $block = i18nblocks_get_language($module, $form['delta']['#value']);
107 $form['i18n'] = array(
108 '#type' => 'fieldset',
109 '#title' => t('Multilingual settings'),
110 '#collapsible' => TRUE
,
112 // Language options will depend on block type
113 $options = array('' => t('All languages')) + locale_language_list('name');
114 if ($module == 'block') {
115 $options[I18N_BLOCK_LOCALIZE
] = t('Translatable block');
117 $form['i18n']['language'] = array(
119 '#title' => t('Language'),
120 '#default_value' => $block->language
,
121 '#options' => $options,
123 // Pass i18ndelta value
124 $form['i18n']['i18ndelta'] = array('#type' => 'value', '#value' => $block->i18ndelta
);
125 $form['#submit'][] = 'i18nblocks_block_admin_configure_submit';
129 // Content type setting: Optional nodeasblock synchronization
131 elseif(module_exists('nodeasblock') && $form_id == 'node_type_form' && isset($form['identity']['type'])) {
132 $form['workflow']['nodeasblockset']['i18n_nodeasblock'] = array(
134 '#title' => t('Create translation blocks automatically'),
135 '#default_value' => variable_get('i18n_nodeasblock_'. $form['#node_type']->type, 0),
136 '#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
137 '#description' => t('Automatic synchronization with blocks generated by nodeasblock module.'),
140 // Node form with nodeasblock settings
141 elseif (isset($form['type']) && ($node = $form['#node']) && $form['type']['#value'] .'_node_form' == $form_id && variable_get("i18n_nodeasblock_$node->type", 0) && isset($form['nodeasblockset'])) {
142 if ($i18nblock = _i18nblocks_nodeasblock($node)) {
143 $block = i18nblocks_get_metablock($i18nblock['delta']);
144 // Override form default values, but not block title
145 foreach( array('block_settings', 'user_vis_settings', 'role_vis_settings','page_vis_settings') as $category) {
146 if (isset($form['nodeasblockset'][$category])) {
147 foreach(element_children($form['nodeasblockset'][$category]) as $field) {
148 if(isset($block->$field) && $field != 'title') {
149 $form['nodeasblockset'][$category][$field]['#default_value'] = $block->$field;
154 // Override first level value
155 foreach(array('status', 'region', 'weight', 'visibility', 'pages', 'custom') as $field) {
156 if($form['nodeasblockset'][$field]['#type'] == 'value') {
157 $form['nodeasblockset'][$field]['#value'] = $block->$field;
158 } elseif(isset($form['nodeasblockset'][$field]['#default_value'])) {
159 $form['nodeasblockset'][$field]['#default_value'] = $block->$field;
162 $form['nodeasblockset']['i18ntxt'] = array('#value' => t('Some block settings have been overridden by the translation block'));
164 // Prepare a new block
166 'type' => 'nodeasblock',
168 'i18nblocks' => array(),
173 $form['i18nblock'] = array('#type' => 'value', '#value' => $i18nblock);
180 * Forms api callback. Submit function
182 function i18nblocks_block_admin_configure_submit($form, &$form_state) {
183 $values = $form_state['values'];
184 i18nblocks_set_language($values['module'], $values['delta'], $values['language']);
185 i18nblocks_save($values);
189 * Get block language data
191 function i18nblocks_get_language($module, $delta) {
192 $block = db_fetch_object(db_query("SELECT l.*, b.i18ndelta FROM {i18n_blocks_language} l LEFT JOIN {i18n_blocks} b ON l.module = b.module AND l.delta = b.delta WHERE l.module = '%s' AND l.delta = %d", $module, $delta));
193 // If no result, return default settings
194 return $block ?
$block : (object)array('language' => '', 'i18ndelta' => 0);
198 * Set block language data
200 function i18nblocks_set_language($module, $delta, $language) {
201 db_query("DELETE FROM {i18n_blocks_language} WHERE module = '%s' AND delta = %d", $module, $delta);
203 db_query("INSERT INTO {i18n_blocks_language} (module, delta, language) VALUES('%s', %d, '%s')", $module, $delta, $language);
208 * Update i18n block data. Only for localizable blocks
210 function i18nblocks_save($values) {
212 if ($values['language'] == I18N_BLOCK_LOCALIZE
) {
213 $values['info'] = t('[Translatable]'.
' '.
$values['info']);
214 if ($values['i18ndelta']) {
215 drupal_write_record('i18n_blocks', $values, 'i18ndelta');
217 drupal_write_record('i18n_blocks', $values);
220 db_query("DELETE FROM {i18n_blocks} WHERE module = '%s' AND delta = %d", $values['module'], $values['delta']);
225 * Load and translate block data
227 function i18nblocks_get_block($delta, $language){
228 // Get block metadata
229 $meta = db_fetch_object(db_query("SELECT i.*, b.title FROM {i18n_blocks} i INNER JOIN {blocks} b ON i.delta = b.delta AND i.module = b.module WHERE i.i18ndelta = '%d'", $delta));
230 // Get block data from module
231 $block = module_invoke($meta->module
, 'block', 'view', $meta->delta
);
234 // Override the default title
236 // Check plain here to allow module generated titles to keep any markup.
237 $block['subject'] = $meta->title
== '<none>' ?
'' : check_plain(tt("blocks:block:$delta:title", $meta->title
, $language));
238 } elseif (!empty($block['subject'])) {
239 $block['subject'] = tt("blocks:block:$delta:title", $block['subject'], $language);
241 $block['content'] = tt("blocks:block:$delta:content", $block['content'], $language);
247 * Implementation of hook_nodeapi
249 function i18nblocks_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
250 if (variable_get("nodeasblock_$node->type", 1) && variable_get("i18n_nodeasblock_$node->type", 0)) {
253 if ($node->i18nblock) {
254 // Copy values from the form before changing any
255 foreach(array('status', 'region', 'weight', 'visibility', 'pages', 'custom', 'info') as $field) {
256 $node->i18nblock['block'][$field] = $node->nodeasblockset[$field];
258 // If the block is new, disable the block changing status before it is saved
259 if (!$node->nodeasblock) {
260 $node->nodeasblockset['status'] = 0;
261 $node->nodeasblockset['region'] = BLOCK_REGION_NONE;
267 // Regenerate all translations for this block
268 // This will run after i18n, translations and nodeasblock
269 if(isset($node->i18nblock) && $metablock = $node->i18nblock) {
270 $metablock['nids'][$node->nid] = $node->nid;
271 // Recreate the translation block. Or delete if no blocks.
272 $metablock['i18nblocks'] = array();
273 $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']));
274 while($trn = db_fetch_object($result)) {
275 $metablock['i18nblocks'][$trn->language] = "nodeasblock:$trn->nid";
277 if ($metablock['i18nblocks']) {
278 // Set values if new block
279 if(!$metablock['info']) {
280 $metablock['info'] = t('Translation: !title', array('!title' => $node->title));
282 $metablock = i18nblocks_save($metablock);
283 // Only if the block is new, rehash block table
284 if (isset($metablock['new'])) {
287 if($block = $metablock['block']) {
288 $block['status'] = 1;
289 $block['delta'] = $metablock['delta'];
290 db_query("UPDATE {blocks} SET status = %d, region = '%s', weight = %d, visibility = %d, pages = '%s', custom = %d WHERE module = 'i18nblocks' AND delta = '%s'",
291 $block['status'], $block['region'], $block['weight'], $block['visibility'], trim($block['pages']), $block['custom'], $block['delta']);
294 } elseif ($metablock['delta']) {
295 i18nblocks_delete($metablock['delta']);
305 * Helper function: collect translation nids and get related nodeasblock block
307 function _i18nblocks_nodeasblock($node) {
308 $nids = $translations = array();
309 if ($node->trid
) { // It is a translation
310 $translations = translation_node_get_translations(array('trid' => $node->trid
));
311 } elseif($node->translation_nid
) { // Translation is just being created
312 $translations = translation_node_get_translations(array('nid' => $node->translation_nid
), TRUE
);
313 $nids[$node->translation_nid
] = $node->translation_nid
;
315 foreach($translations as
$lang => $trn) {
316 $nids[$trn->nid
] = $trn->nid
;
318 if($node->nid
) { // Updating existing node, no translations yet
319 $nids[$node->nid
] = $node->nid
;
321 // Check for existing block
322 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))) {
323 $i18nblock['nids'] = $nids;
328 * Form for multilingual blocks
330 function i18nblocks_form($metablock, $delta = NULL
){
331 $languages = i18n_supported_languages();
332 $modules = array_intersect(module_list(), module_implements('block'));
333 // Compile list of available blocks
334 $blocklist = array('' => t(' -- '));
335 foreach (module_implements('block') as
$module) {
336 if($module != 'i18nblocks') { // Avoid this module's blocks, could be funny :-)
337 if (is_array($module_blocks = module_invoke($module, 'block', 'list'))) {
338 foreach($module_blocks as
$number => $block) {
339 $blocklist[$module.
':'.
$number] = $block['info'].
"($module)";
344 $form['info'] = array('#type' => 'textfield', '#title' => t('Block description'),
345 '#default_value' => $metablock->info ?
$metablock->info
: t('Multilingual block !number', array('!number' => $delta)),
349 $form['type'] = array('#type' => 'value', '#value' => $metablock->type ?
$metablock->type
: '');
350 $form['i18nblocks'] = array('#type' => 'fieldset', '#tree' => TRUE
, '#title' => t('Select the block to be displayed for each language'));
352 foreach($languages as
$lang => $langname){
353 $block = isset($metablock->blocks
[$lang]) ?
$metablock->blocks
[$lang] :NULL
;
354 $form['i18nblocks'][$lang] = array(
356 '#title' => $langname,
357 '#default_value' => $block ?
$block->module.
':'.
$block->delta
: '',
358 '#options' => $blocklist
361 // Submit button only for new blocks
363 $form['delete'] = array('#value' => l(t('Delete this block'), 'admin/build/block/i18n/delete/'.
$delta));
364 $form['type'] = array(
366 '#default_value' => $metablock->type
,
367 '#options' => array('' => t('Normal translation block')),
370 if (module_exists('nodeasblock')) {
371 $form['type']['#options']['nodeasblock'] = t('Node as block with automatic synchronization');
372 $form['type']['#disabled'] = FALSE
;
375 $form['submit'] = array('#type' => 'submit', '#value' => t('Create block'));
381 * Add a new metablock and go to settings page
383 function i18nblocks_admin($op = 'add', $delta = NULL
, $confirm = FALSE
){
385 $metablock = new
StdClass();
386 $metablock->info
= t('New multilingual block');
387 return drupal_get_form('i18nblocks_form', $metablock);
388 } elseif($op == 'delete' && $delta && $block = i18nblocks_get_metablock($delta)) {
389 i18nblocks_delete($delta);
390 drupal_set_message("The block has been deleted");
391 drupal_goto('admin/build/block');
395 function i18nblocks_form_submit($form_id, $form_values){
396 i18nblocks_save($form_values, NULL
);
397 return 'admin/build/block';
401 * Db layer: for now it stores each block as a variable
403 function i18nblocks_get_metablock($delta, $getblocks = FALSE
){
404 $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));
406 $result = db_query("SELECT * FROM {i18n_blocks_i18n} WHERE bid = '%s'", $delta);
407 $metablock->blocks
= array();
408 while ($block = db_fetch_object($result)) {
409 $metablock->blocks
[$block->language
] = $block;
417 function i18nblocks_delete($delta) {
418 db_query("DELETE FROM {i18n_blocks} WHERE delta = '%s'", $delta);
419 db_query("DELETE FROM {i18n_blocks_i18n} WHERE bid = '%s'", $delta);