3720f6137794057e5d2e31712fbe30f2f2d8963e
[project/i18n.git] / i18ntaxonomy / i18ntaxonomy.module
1 <?php
2 /**
3 * @file
4 * i18n taxonomy module
5 *
6 * Internationalization (i18n) package
7 *
8 * This module groups together all existing i18n taxonomy functionality
9 * providing several options for taxonomy translation
10 *
11 * Translates taxonomy term for selected vocabularies running them through the localization system
12 * It also translates terms for views filters and views results
13 *
14 * @author Jose A. Reyero, 2004
15 */
16
17 /**
18 * Implementation of hook_help().
19 */
20 function i18ntaxonomy_help($section = 'admin/help#i18n' ) {
21 switch ($section) {
22 case 'admin/help#i18ntaxonomy' :
23 $output = '<p>'.t('This module adds support for for multilingual taxonomy. You can set up multilingual options for each vocabulary:').'</p>';
24 $output .= '<ul>';
25 $output .= '<li>'.t('A language can be assigned globaly for a vocabulary').'</li>';
26 $output .= '<li>'.t('Different terms for each language with translation relationships.').'</li>';
27 $output .= '<li>'.t('Terms can be common to all languages but may be localized.').'</li>';
28 $output .= '</ul>';
29 $output .= '<p>'. t('For more information please read the <a href="@i18n">on-line help pages</a>.', array('@i18n' =>'http://drupal.org/node/31631')) .'</p>';
30 return $output;
31 case 'admin/settings/i18n':
32 $output = '<ul>';
33 $output .= '<li>'.t('To set up multilingual options for vocabularies go to !configure_taxonomy', array('!configure_taxonomy' => l(t('Taxonomy configuration page'), 'admin/content/taxonomy'))).'</li>';
34 $output . '</ul>';
35 return $output;
36 }
37 }
38 /**
39 * Modes for multilingual vocabularies
40 */
41 // No multilingual options
42 define('I18N_TAXONOMY_NONE', 0);
43 // Run through the localization system
44 define('I18N_TAXONOMY_LOCALIZE', 1);
45 // Predefined language for all terms
46 define('I18N_TAXONOMY_LANGUAGE', 2);
47 // Multilingual terms, translatable
48 define('I18N_TAXONOMY_TRANSLATE', 3);
49
50 /**
51 * Returns list of vocabulary modes
52 */
53 function _i18ntaxonomy_vocabulary_options() {
54 return array(
55 I18N_TAXONOMY_NONE => t('No translation'),
56 I18N_TAXONOMY_LOCALIZE => t('Localize terms. Terms are common for all languages but their name and description may be localized.'),
57 I18N_TAXONOMY_TRANSLATE => t('Per language terms. Different terms will be allowed for each language and they can be translated.'),
58 I18N_TAXONOMY_LANGUAGE => t('Set language to vocabulary. The vocabulary will have a global language and it will only show up for pages in that language.'),
59 );
60 }
61 /**
62 * Implementation of hook_menu().
63 */
64 function i18ntaxonomy_menu() {
65 $items['admin/content/taxonomy/%taxonomy_vocabulary/translation'] = array(
66 'title' => 'Add term',
67 'page callback' => 'i18n_taxonomy_page_vocabulary',
68 'page arguments' => array(3),
69 'type' => MENU_LOCAL_TASK,
70 'parent' => 'admin/content/taxonomy/%taxonomy_vocabulary',
71 'file' => 'taxonomy.admin.inc',
72 );
73 return $items;
74 }
75
76 /**
77 * Implementation of hook_locale().
78 */
79 function i18ntaxonomy_locale($op = 'groups') {
80 switch ($op) {
81 case 'groups':
82 return array('taxonomy' => t('Taxonomy'));
83 }
84 }
85 /**
86 * Implementation of hook_alter_translation_link().
87 *
88 * Replaces links with pointers to translated versions of the content.
89 */
90 function i18ntaxonomy_translation_link_alter(&$links, $path) {
91 if (preg_match("/^(taxonomy\/term\/)([^\/]*)(.*)$/", $path, $matches)) {//or at a taxonomy-listing?
92 foreach ($links as $langcode => $link) {
93 if ($str_tids = i18ntaxonomy_translation_tids($matches[2], $langcode)) {
94 $links[$langcode]['href'] = "taxonomy/term/$str_tids". $matches[3];
95 }
96 }
97 }
98 }
99
100 /**
101 * Get translated term's tid
102 *
103 * @param $tid
104 * Node nid to search for translation
105 * @param $language
106 * Language to search for the translation, defaults to current language
107 * @param $default
108 * Value that will be returned if no translation is found
109 * @return
110 * Translated term tid if exists, or $default
111 */
112 function i18ntaxonomy_translation_term_tid($tid, $language = NULL, $default = NULL) {
113 $translation = db_result(db_query("SELECT t.tid FROM {term_data} t INNER JOIN {term_data} a ON t.trid = a.trid AND t.tid != a.tid WHERE a.tid = %d AND t.language = '%s' AND t.trid", $tid, $language ? $language : i18n_get_lang()));
114 return $translation ? $translation : $default;
115 }
116
117 /**
118 * Returns an url for the translated taxonomy-page, if exists
119 */
120 function i18ntaxonomy_translation_tids($str_tids, $lang) {
121 if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str_tids)) {
122 $separator = '+';
123 // The '+' character in a query string may be parsed as ' '.
124 $tids = preg_split('/[+ ]/', $str_tids);
125 }
126 else if (preg_match('/^([0-9]+,)*[0-9]+$/', $str_tids)) {
127 $separator = ',';
128 $tids = explode(',', $str_tids);
129 }
130 else {
131 return;
132 }
133 $translated_tids = array();
134 foreach ($tids as $tid) {
135 if ($translated_tid = i18ntaxonomy_translation_term_tid($tid, $lang)) {
136 $translated_tids[] = $translated_tid;
137 }
138 }
139 return implode($separator, $translated_tids);
140 }
141 /**
142 * Implementation of hook_taxonomy
143 *
144 * $edit parameter may be an array or an object !!
145 */
146 function i18ntaxonomy_taxonomy($op, $type, $edit = NULL) {
147 $edit = (array)$edit;
148 switch ("$type/$op") {
149 case 'term/insert':
150 case 'term/update':
151 $tid = $edit['tid'];
152 $language = isset($edit['language']) ? $edit['language'] : '';
153 db_query("UPDATE {term_data} SET language='%s' WHERE tid=%d", $language, $tid);
154 // From translation module
155 if (!$language && !empty($edit['trid'])) {
156 // Removed language, remove trid
157 db_query('UPDATE {term_data} SET trid = 0 WHERE tid = %d', $tid);
158 if(db_affected_rows()) drupal_set_message(t('Removed translation information from term'));
159 }
160 // Update strings for localizable vocabulary
161 if (i18ntaxonomy_vocabulary($edit['vid']) == I18N_TAXONOMY_LOCALIZE) {
162 tt("taxonomy:term:$tid:name", $edit['name'], NULL, TRUE);
163 tt("taxonomy:term:$tid:description", $edit['description'], NULL, TRUE);
164 }
165 break;
166 case 'vocabulary/insert':
167 case 'vocabulary/update':
168 $vid = $edit['vid'];
169 // Update vocabulary settings
170 if (isset($edit['i18nmode'])) {
171 i18ntaxonomy_vocabulary($vid, $edit['i18nmode']);
172
173 $language = isset($edit['language']) ? $edit['language'] : '';
174 db_query("UPDATE {vocabulary} SET language='%s' WHERE vid = %d", $language, $edit['vid']);
175 if ($language && $op == 'update') {
176 db_query("UPDATE {term_data} SET language='%s' WHERE vid = %d", $edit['language'], $edit['vid']);
177 drupal_set_message(t('Reset language for all terms.'));
178 }
179 // Always add vocabulary translation if !$language
180 if (!$language) {
181 tt("taxonomy:vocabulary:$vid:name", $edit['name'], NULL, TRUE);
182 }
183 }
184 break;
185 }
186 }
187
188 /**
189 * Implementation of hook_db_rewrite_sql()
190 */
191 function i18ntaxonomy_db_rewrite_sql($query, $primary_table, $primary_key){
192 // No rewrite for administration pages
193 if (arg(0) == 'admin') return;
194
195 switch ($primary_table) {
196 case 't':
197 case 'v':
198 // Taxonomy queries
199 // When loading specific terms, vocabs, language conditions shouldn't apply
200 if (preg_match("/WHERE.* $primary_table\.tid\s*(=\s*\d|IN)/", $query)) return;
201 // Taxonomy for specific node
202 if (preg_match("/WHERE r\.nid = \%d/", $query)) return;
203 $result['where'] = i18n_db_rewrite_where($primary_table, 'taxonomy');
204 return $result;
205 }
206 }
207
208 /**
209 * Implementation of hook_form_alter
210 *
211 * This is the place to add language fields to all forms
212 */
213 function i18ntaxonomy_form_alter(&$form, $form_state, $form_id) {
214 switch($form_id){
215 case 'taxonomy_overview_vocabularies':
216 $vocabularies = taxonomy_get_vocabularies();
217 $languages = i18n_supported_languages();
218 foreach ($vocabularies as $vocabulary) {
219 if($vocabulary->language) $form[$vocabulary->vid]['type']['#value'] = $form[$vocabulary->vid]['type']['#value'].'&nbsp('.$languages[$vocabulary->language].')';
220 }
221 break;
222 case 'taxonomy_form_vocabulary': // Taxonomy vocabulary
223 if (isset($form['vid'])) {
224 $vocabulary = taxonomy_vocabulary_load($form['vid']['#value']);
225 $mode = i18ntaxonomy_vocabulary($vocabulary->vid);
226 } else {
227 $mode = I18N_TAXONOMY_NONE;
228 }
229 $form['i18n'] = array(
230 '#type' => 'fieldset',
231 '#title' => t('Multilingual options'),
232 '#collapsible' => TRUE,
233 '#weight' => 0,
234 );
235 $form['i18n']['i18nmode'] = array(
236 '#type' => 'radios',
237 '#title' => t('Translation mode'),
238 '#options' => _i18ntaxonomy_vocabulary_options(),
239 '#default_value' => $mode,
240 );
241
242 break;
243
244 case 'taxonomy_form_term': // Taxonomy term
245 $vocabulary = (object)$form['#vocabulary'];
246 $term = (object)$form['#term'];
247 // Add language field or not depending on taxonomy mode
248 switch (i18ntaxonomy_vocabulary($vocabulary->vid)) {
249 case I18N_TAXONOMY_TRANSLATE:
250 $form['identification']['language'] = array(
251 '#type' => 'select',
252 '#title' => t('Language'),
253 '#default_value' => isset($term) && !empty($term->language) ? $term->language : '',
254 '#options' => array('' => '') + locale_language_list('name'),
255 '#description' => t('This term belongs to a multilingual vocabulary.'),
256 );
257 break;
258 case I18N_TAXONOMY_LANGUAGE:
259 $form['language'] = array('#type' => 'value', '#value' => $vocabulary->language);
260 break;
261 case I18N_TAXONOMY_NONE:
262 case I18N_TAXONOMY_LOCALIZE:
263 $form['language'] = array('#type' => 'value', '#value' => '');
264 break;
265 }
266 break;
267 default:
268 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id
269 && ($node = $form['#node']) && isset($form['taxonomy']) ) {
270 // Node form. Translate vocabularies
271 i18ntaxonomy_node_form($form);
272 }
273 }
274 }
275
276 /**
277 * Handle node form taxonomy
278 */
279 function i18ntaxonomy_node_form(&$form) {
280 $node = $form['#node'];
281 if (!isset($node->taxonomy)) {
282 if (!empty($node->nid)) {
283 $terms = taxonomy_node_get_terms($node->nid);
284 }
285 else {
286 $terms = array();
287 }
288 }
289 else {
290 $terms = $node->taxonomy;
291 }
292 // Regenerate the whole field for translatable vocabularies
293 foreach (element_children($form['taxonomy']) as $vid) {
294 if (is_numeric($vid) && i18ntaxonomy_vocabulary($vid) == I18N_TAXONOMY_LOCALIZE) {
295 // Rebuild this vocabulary's form
296 $vocabulary = taxonomy_vocabulary_load($vid);
297 // Extract terms belonging to the vocabulary in question.
298 $default_terms = array();
299 foreach ($terms as $term) {
300 if ($term->vid == $vid) {
301 $default_terms[$term->tid] = $term;
302 }
303 }
304
305 $form['taxonomy'][$vid] = i18ntaxonomy_vocabulary_form($vocabulary->vid, array_keys($default_terms));
306 $form['taxonomy'][$vid]['#weight'] = $vocabulary->weight;
307 $form['taxonomy'][$vid]['#required'] = $vocabulary->required;
308 }
309 }
310 }
311
312 /**
313 * Generate a form element for selecting terms from a vocabulary.
314 * Translates all translatable strings.
315 */
316 function i18ntaxonomy_vocabulary_form($vid, $value = 0, $help = NULL, $name = 'taxonomy') {
317 $vocabulary = taxonomy_vocabulary_load($vid);
318 $help = $vocabulary->help ? tt("taxonomy:vocabulary:$vid:help", $vocabulary->help) : '';
319 if ($vocabulary->required) {
320 $blank = 0;
321 }
322 else {
323 $blank = '<'. t('none') .'>';
324 }
325
326 return _i18ntaxonomy_term_select(check_plain(tt("taxonomy:vocabulary:$vid:name", $vocabulary->name)), $name, $value, $vid, $help, intval($vocabulary->multiple), $blank);
327 }
328
329 // Produces translated tree
330 function _i18ntaxonomy_term_select($title, $name, $value, $vocabulary_id, $description, $multiple, $blank, $exclude = array()) {
331 $tree = taxonomy_get_tree($vocabulary_id);
332 $options = array();
333
334 if ($blank) {
335 $options[0] = $blank;
336 }
337 if ($tree) {
338 foreach ($tree as $term) {
339 if (!in_array($term->tid, $exclude)) {
340 $choice = new stdClass();
341 $choice->option = array($term->tid => str_repeat('-', $term->depth) . tt("taxonomy:term:$term->tid:name", $term->name));
342 $options[] = $choice;
343 }
344 }
345 if (!$blank && !$value) {
346 // required but without a predefined value, so set first as predefined
347 $value = $tree[0]->tid;
348 }
349 }
350
351 return array('#type' => 'select',
352 '#title' => $title,
353 '#default_value' => $value,
354 '#options' => $options,
355 '#description' => $description,
356 '#multiple' => $multiple,
357 '#size' => $multiple ? min(9, count($options)) : 0,
358 '#weight' => -15,
359 '#theme' => 'taxonomy_term_select',
360 );
361 }
362 /**
363 * Returns a list for terms for vocabulary, language
364 */
365 function i18ntaxonomy_vocabulary_get_terms($vid, $lang, $status = 'all') {
366 switch($status){
367 case 'translated':
368 $andsql = ' AND trid > 0';
369 break;
370 case 'untranslated':
371 $andsql = ' AND trid = 0';
372 break;
373 default:
374 $andsql = '';
375 }
376 $result = db_query("SELECT * FROM {term_data} WHERE vid=%d AND language='%s' $andsql", $vid, $lang);
377 $list = array();
378 while ($term = db_fetch_object($result)) {
379 $list[$term->tid] = $term->name;
380 }
381 return $list;
382 }
383
384 /**
385 * Multilingual Taxonomy
386 *
387 */
388
389 /**
390 * This is the callback for taxonomy translations
391 *
392 * Gets the urls:
393 * admin/content/taxonomy/i18n/term/xx
394 * admin/content/taxonomy/i18n/term/new/xx
395 * admin/content/taxonomy/vid/translation/op/trid
396 */
397
398 function i18ntaxonomy_page_vocabulary($vocabulary) {
399 $op = $_POST['op'] ? $_POST['op'] : arg(5);
400 $edit = $_POST['edit'];
401
402 switch ($op) {
403 case t('Save'):
404 case 'edit':
405 drupal_set_title(t('Edit term translations'));
406 $output = drupal_get_form('i18ntaxonomy_translation_term_form', $vocabulary->vid, arg(6), $edit);
407 break;
408 case t('Submit'):
409 drupal_set_title(t('Submit'));
410 i18ntaxonomy_translation_term_save($edit);
411 $output = i18ntaxonomy_translation_overview($vocabulary->vid);
412 break;
413 case 'delete':
414 //print theme('page', node_delete($edit), t('Delete'));
415 break;
416 default:
417 $output = i18ntaxonomy_translation_overview($vocabulary->vid);
418 }
419 return $output;
420 }
421
422 /**
423 * Generate a tabular listing of translations for vocabularies.
424 */
425 function i18ntaxonomy_translation_overview($vid) {
426 $vocabulary = taxonomy_vocabulary_load($vid);
427 drupal_set_title(check_plain($vocabulary->name));
428
429 $languages = i18n_supported_languages();
430 $header = array_merge($languages, array(t('Operations')));
431 $links = array();
432 $types = array();
433 // Get terms/translations for this vocab
434 $result = db_query('SELECT * FROM {term_data} t WHERE vid=%d',$vocabulary->vid);
435 $terms = array();
436 while ($term = db_fetch_object($result)) {
437 if($term->trid && $term->language) {
438 $terms[$term->trid][$term->language] = $term;
439 }
440 }
441 // Reorder data for rows and languages
442 foreach ($terms as $trid => $terms) {
443 $thisrow = array();
444 foreach ($languages as $lang => $name) {
445 if (array_key_exists($lang, $terms)) {
446 $thisrow[] = $terms[$lang]->name;
447 }
448 else {
449 $thisrow[] = '--';
450 }
451 }
452 $thisrow[] = l(t('edit'), "admin/content/taxonomy/$vid/translation/edit/$trid");
453 $rows[] = $thisrow;
454 }
455 $output .= theme('table', $header, $rows);
456 $output .= l(t('new translation'), "admin/content/taxonomy/$vid/translation/edit/new");
457 return $output;
458 }
459
460 /**
461 * Produces a vocabulary translation form
462 */
463 function i18ntaxonomy_translation_term_form($vid, $trid = NULL, $edit = array()) {
464 $languages = i18n_supported_languages();
465 if ($trid == 'new') {
466 $translations = array();
467 } else {
468 $form['trid'] = array('#type' => 'hidden', '#value' => $trid);
469 $translations = i18ntaxonomy_term_get_translations(array('trid' =>$trid));
470 }
471 //var_dump($translations);
472 $vocabulary = taxonomy_vocabulary_load($vid);
473
474 // List of terms for languages
475 foreach ($languages as $lang => $langname) {
476 $current = isset($translations[$lang]) ? $translations[$lang]->tid : '';
477 $list = translation_vocabulary_get_terms($vid, $lang, 'all');
478 $list[''] = '--';
479 $form[$lang] = array('#type' => 'fieldset', '#tree' => TRUE);
480 $form[$lang]['tid'] = array(
481 '#type' => 'select',
482 '#title' => $langname,
483 '#default_value' => $current,
484 '#options' => $list
485 );
486 $form[$lang]['old'] = array('#type' => 'hidden', '#value' =>$current);
487 }
488 $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
489 $form['destination'] = array('#type' => 'hidden', '#value' => 'admin/content/taxonomy/'.arg(3).'/translation');
490 return $form;
491 }
492
493 /**
494 * Form callback: Process vocabulary translation form
495 */
496 function i18ntaxonomy_translation_term_form_submit($form_id, $form_values) {
497 i18ntaxonomy_translation_save($form_values, $form_values['trid']);
498 drupal_set_message(t('Term translations have been updated'));
499 }
500
501 /**
502 * Save taxonomy term translations
503 *
504 * @param $terms
505 * Array of terms indexed by language
506 * @param $trid
507 * Optional translation set id
508 */
509 function i18ntaxonomy_translation_save($terms, $trid = 0) {
510 // Delete old translations for this trid
511 if ($trid){
512 db_query("UPDATE {term_data} SET trid = 0 WHERE trid= %d", $trid);
513 }
514 // Now pick up all the tids in an array
515 $translations = array();
516 foreach (i18n_supported_languages() as $lang => $name) {
517 if (isset($terms[$lang]) && ($term = (array)$terms[$lang]) && $tid = $term['tid']) {
518 $translations[$lang] = $tid;
519 }
520 }
521 // Now set a translation set with all these terms.
522 if (count($translations)) {
523 $trid = (is_numeric($trid) && $trid) ? $trid : db_next_id('{term_data}_trid');
524 db_query('UPDATE {term_data} SET trid = %d WHERE tid IN(%s)', $trid, implode(',',$translations));
525 }
526 }
527
528
529 /**
530 * Get term translations
531 *
532 * @return
533 * An array of the from lang => Term
534 */
535 function i18ntaxonomy_term_get_translations($params, $getall = TRUE) {
536 foreach($params as $field => $value) {
537 $conds[] = "i.$field = '%s'";
538 $values[] = $value;
539 }
540 if(!$getall){ // If not all, a parameter must be tid
541 $conds[] = "t.tid != %d";
542 $values[] = $params['tid'];
543 }
544 $conds[] = "t.trid != 0";
545 $sql = 'SELECT t.* FROM {term_data} t INNER JOIN {term_data} i ON t.trid = i.trid WHERE '. implode(' AND ', $conds);;
546 $result = db_query($sql, $values);
547 $items = array();
548 while ($data = db_fetch_object($result)) {
549 $items[$data->language] = $data;
550 }
551 return $items;
552 }
553
554
555 /**
556 * Like nat_get_terms() but without caching
557 */
558 function i18ntaxonomy_nat_get_terms($nid) {
559 $return = array();
560
561 $result = db_query("SELECT td.* FROM {nat} n INNER JOIN {term_data} td USING (tid) WHERE n.nid = %d", $nid);
562 while ($term = db_fetch_object($result)) {
563 $return[$term->tid] = $term;
564 }
565
566 return $return;
567 }
568
569
570 /**
571 * Implementation of hook_nodeapi()
572 *
573 * Prepare node for translation
574 */
575 function i18ntaxonomy_nodeapi(&$node, $op) {
576 switch ($op) {
577 case 'view':
578 // This runs after taxonomy:nodeapi, so we just localize terms here
579 if ($op == 'view' && array_key_exists('taxonomy', $node)) {
580 $node->taxonomy = i18ntaxonomy_localize_terms($node->taxonomy);
581 }
582 break;
583 case 'prepare translation':
584 $source = $node->translation_source;
585 // Taxonomy translation
586 if (is_array($source->taxonomy)) {
587 // Set translated taxonomy terms
588 $node->taxonomy = i18ntaxonomy_translate_terms($source->taxonomy, $node->language);
589 }
590 break;
591 }
592 }
593
594 /**
595 * Translate an array of taxonomy terms
596 *
597 * Translates all terms with language, just passing over terms without it
598 */
599 function i18ntaxonomy_translate_terms($taxonomy, $langcode) {
600 $translation = array();
601 foreach ($taxonomy as $index => $term) {
602 if ($term->language && $term->language != $langcode) {
603 $translated_terms = i18ntaxonomy_term_get_translations(array('tid' => $term->tid));
604 if ($translated_terms && $newterm = $translated_terms[$langcode]) {
605 $translation[$newterm->tid] = $newterm;
606 }
607 } else {
608 // Term has no language. Should be ok
609 $translation[$index] = $term;
610 }
611 }
612 return $translation;
613 }
614 /**
615 * Implementation of hook_views_pre_view().
616 *
617 * Translate table header for taxonomy fields
618 * //field[i][id] = term_node_1.name, translate table header
619 * and replace handler for that field
620 */
621 function i18ntaxonomy_views_pre_view(&$view, &$items) {
622 //var_dump($view);
623 $translate = variable_get('i18ntaxonomy_vocabularies', array());
624 foreach($view->field as $index => $data) {
625 $matches = array();
626 if($data['id'] == 'term_node.name') {
627 // That's a full taxonomy box
628 $view->field[$index]['handler'] = 'i18ntaxonomy_views_handler_field_allterms';
629 } elseif(preg_match("/term_node_(\d+)\.name/", $data['id'], $matches)) {
630 $vid = $matches[1];
631 if ($translate[$vid]) {
632 // Set new handler for this field
633 $view->field[$index]['handler'] = 'i18ntaxonomy_views_handler_field_allterms';
634 }
635 }
636 }
637
638 }
639
640 /**
641 * Field handler for taxonomy term fields
642 *
643 * Remake of views_handler_field_allterms with term name translation
644 */
645 function i18ntaxonomy_views_handler_field_allterms($fieldinfo, $fielddata, $value, $data) {
646 if ($fieldinfo['vocabulary']) {
647 $terms = taxonomy_node_get_terms_by_vocabulary($data->nid, $fieldinfo['vocabulary']);
648 }
649 else {
650 $terms = taxonomy_node_get_terms($data->nid);
651 }
652 // Translate all these terms
653 _i18ntaxonomy_translate_terms($terms);
654
655 if ($fielddata['options'] == 'nolink') {
656 foreach ($terms as $term) {
657 $links[] = check_plain($term->name);
658 }
659 $links = !empty($links) ? implode(' | ', $links) : '';
660 }
661 else {
662 $node = new stdClass();
663 $node->taxonomy = $terms;
664 $links = theme('links', taxonomy_link('taxonomy terms', $node));
665 }
666 return $links;
667 }
668
669 // Translate an array of term objects
670 function i18ntaxonomy_localize_terms($terms, $fields = array('name')) {
671 $translation = array();
672 $localize = i18ntaxonomy_vocabulary(NULL, I18N_TAXONOMY_LOCALIZE);
673 foreach ($terms as $index => $term) {
674 if (in_array($term->vid, $localize)) {
675 foreach ($fields as $property ) {
676 $translation[$index]->$property = tt("taxonomy:term:$term->tid:$property", $term->name);
677 }
678 } else {
679 $translation[$index] = $term;
680 }
681 }
682 return $translation;
683 }
684
685 // Get a list of vocabularies and terms
686 function _i18ntaxonomy_vocabulary_terms($vid = NULL, $fullname = TRUE) {
687 $tids = array();
688 if (is_numeric($vid)) {
689 $where = "WHERE td.vid = $vid";
690 } elseif(is_array($vid)) {
691 $where = "WHERE td.vid IN(".implode(',', $vid).')';
692 }
693 $result = db_query("SELECT DISTINCT(td.tid), td.name, td.weight, v.name as vocabname, v.weight FROM {term_data} td LEFT JOIN {vocabulary} v ON v.vid = td.vid $where ORDER BY v.weight, v.name, td.weight, td.name");
694 while ($obj = db_fetch_object($result)) {
695 $tids[$obj->tid] = $fullname ? t($obj->vocabname).': '.t($obj->name) : t($obj->name);
696 }
697
698 return $tids;
699 }
700
701 /**
702 * Taxonomy vocabulary settings
703 *
704 * - If $vid and not $value, returns mode for vid
705 * - If $vid and $value, sets mode for vid
706 * - If !$vid and !$value returns all settings
707 * - If !$vid and $value returns all vids for this mode
708 *
709 * @param $vid
710 * Vocabulary id
711 * @param $value
712 * Vocabulary mode
713 *
714 */
715 function i18ntaxonomy_vocabulary($vid = NULL, $mode = NULL) {
716 $options = variable_get('i18ntaxonomy_vocabulary', array());
717 if ($vid && $mode) {
718 $options[$vid] = $mode;
719 variable_set('i18ntaxonomy_vocabulary', $options);
720 } elseif ($vid) {
721 return array_key_exists($vid, $options) ? $options[$vid] : I18N_TAXONOMY_NONE;
722 } elseif ($mode) {
723 return array_keys($options, $mode);
724 } else {
725 return $options;
726 }
727 }