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