Typo fixed.
[project/i18n.git] / i18n.module
1 <?php
2 // $Id$
3
4 /**
5 * @file
6 * Internationalization (i18n) module
7 *
8 * This module extends multilingual support being the base module for the i18n package.
9 * - Multilingual variables
10 * - Extended languages for nodes
11 * - Extended language API
12 *
13 * @author Jose A. Reyero, 2004
14 */
15
16 // Some constants. Language support modes for content
17 define('LANGUAGE_SUPPORT_NONE', 0);
18 define('LANGUAGE_SUPPORT_NORMAL', 1);
19 define('LANGUAGE_SUPPORT_EXTENDED', 2);
20
21 /**
22 * Implementation of hook_init().
23 *
24 * Will initialize language dependent variables.
25 * Modify rewriting conditions when viewing specific nodes.
26 *
27 * Special fix for site_frontpage, that may have been used before the language variables are loaded.
28 */
29 function i18n_init() {
30 // If not in bootstrap, variable init.
31 if (!_i18n_is_bootstrap()) {
32 $default_frontpage = variable_get('site_frontpage', 'node');
33
34 i18n_variable_init();
35
36 // Now we check whether this is the frontpage and it should be a different one.
37 if ($default_frontpage != variable_get('site_frontpage', 'node') && $_GET['q'] == drupal_get_normal_path($default_frontpage)) {
38 $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
39 }
40 }
41 }
42
43 /**
44 * Implementation of hook_help().
45 */
46 function i18n_help($path = 'admin/help#i18n', $arg) {
47 switch ($path) {
48 case 'admin/help#i18n' :
49 $output = '<p>'. t('This module improves support for multilingual content in Drupal sites:') .'</p>';
50 $output .= '<ul>';
51 $output .= '<li>'. t('Shows content depending on page language.') .'</li>';
52 $output .= '<li>'. t('Handles multilingual variables.') .'</li>';
53 $output .= '<li>'. t('Extended language option for chosen content types. For these content types transations will be allowed for all defined languages, not only for enabled ones.') .'</li>';
54 $output .= '<li>'. t('Provides a block for language selection and two theme functions: <i>i18n_flags</i> and <i>i18n_links</i>.') .'</li>';
55 $output .= '</ul>';
56 $output .= '<p>'. t('This is the base module for several others adding different features:') .'</p>';
57 $output .= '<ul>';
58 $output .= '<li>'. t('Multilingual menu items') .'</li>';
59 $output .= '<li>'. t('Multilingual taxonomy adds a language field for taxonomy vocabularies and terms') .'</li>';
60 $output .= '</ul>';
61 $output .= '<p>'. t('For more information, see the online handbook entry for <a href="@i18n">Internationalization module</a>.', array('@i18n' => 'http://drupal.org/node/133977')) .'</p>';
62 return $output;
63
64 case 'admin/settings/i18n':
65 $output = '<ul>';
66 $output .= '<li>'. t('To manage languages go to the <a href="@configure_languages">languages configuration page</a>.', array('@configure_languages' => url('admin/settings/language'))) .'</li>';
67 $output .= '<li>'. t('To enable multilingual support for specific content types go to <a href="@configure_content_types">configure content types</a>.', array('@configure_content_types' => url('admin/content/types'))) .'</li>';
68 $output .= '</ul>';
69 return $output;
70 }
71 }
72
73 /**
74 * Implementation of hook_menu().
75 */
76 function i18n_menu() {
77 $items['admin/settings/i18n'] = array(
78 'title' => 'Multilingual system',
79 'description' => 'Configure extended options for multilingual content and translations.',
80 'page callback' => 'drupal_get_form',
81 'page arguments' => array('i18n_admin_settings'),
82 'access arguments' => array('administer site configuration'),
83 'file' => 'i18n.admin.inc',
84 );
85 $items['admin/settings/i18n/main'] = array(
86 'title' => 'Internationalization',
87 'type' => MENU_DEFAULT_LOCAL_TASK,
88 );
89
90 return $items;
91 }
92
93 /**
94 * Implementation of hook_menu_alter().
95 *
96 * Take over the node translation page.
97 */
98 function i18n_menu_alter(&$items) {
99 // dsm($router_items);
100 /*
101 $items['node/%node/translate']['page callback'] = 'i18n_translation_node_overview';
102 $items['node/%node/translate']['file'] = 'i18n.pages.inc';
103 $items['node/%node/translate']['module'] = 'i18n';
104 */
105 /**
106 $items = array();
107 $items['node/%node/translate'] = array(
108 'title' => 'Translate',
109 'page callback' => 'translation_node_overview',
110 'page arguments' => array(1),
111 'access callback' => '_translation_tab_access',
112 'access arguments' => array(1),
113 'type' => MENU_LOCAL_TASK,
114 'weight' => 2,
115 'file' => 'i18n.pages.inc',
116 );
117 return $items;
118 */
119 }
120
121 /**
122 * Implementation of hook_nodeapi().
123 */
124 /*
125 function i18n_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
126 if (variable_get("i18n_node_$node->type", 0)) {
127 switch ($op) {
128 case 'load':
129 return db_fetch_array(db_query("SELECT trid, language, status AS i18n_status FROM {i18n_node} WHERE nid=%d", $node->nid));
130
131 case 'insert':
132 case 'update':
133 db_query("DELETE FROM {i18n_node} WHERE nid=%d",$node->nid);
134 if ($node->language){
135 // Assign a trid from the beginning
136 db_query("INSERT INTO {i18n_node} (nid, trid, language, status) VALUES(%d, '%d', '%s', '%d')", $node->nid, $node->trid, $node->language, $node->i18n_status);
137 }
138 // Handle menu items. Fixes duplication issue and language for menu items which happens when editing nodes in languages other than current.
139 if (isset($node->menu) && !$node->menu['delete'] && $node->menu['title']) {
140 $item = $node->menu;
141 $item['path'] = ($item['path']) ? $item['path'] : "node/$node->nid";
142 $item['type'] = $item['type'] | MENU_MODIFIED_BY_ADMIN;
143 if ($item['mid']) {
144 // Update menu item.
145 db_query("UPDATE {menu} SET pid = %d, path = '%s', title = '%s', description = '%s', weight = %d, type = %d, language = '%s' WHERE mid = %d", $item['pid'], $item['path'], $item['title'], $item['description'], $item['weight'], $item['type'], $node->language, $item['mid']);
146 drupal_set_message(t('The menu item %title has been updated with node language.', array('%title' => $item['title'])));
147 }
148 elseif (SAVED_NEW == menu_save_item($item)) {
149 // Creating new menu item with node language.
150 db_query("UPDATE {menu} SET language = '%s' WHERE mid = %d", $node->language, $item['mid']);
151 drupal_set_message(t('The menu item %title has been added with node language.', array('%title' => $item['title'])));
152 }
153 menu_rebuild();
154 unset($node->menu); // Avoid further processing by menu module.
155 }
156 // Pathauto integration. Dynamic replacement of variables to allow different patterns per language.
157 if (module_exists('path') && module_exists('pathauto')) {
158 // Language for pathauto variables is either node language or default language.
159 $language = $node->language ? $node->language : i18n_default_language();
160 if ($language != i18n_get_lang()) {
161 i18n_variable_init($language, 'pathauto_node');
162 }
163 }
164 break;
165
166 case 'delete':
167 db_query('DELETE FROM {i18n_node} WHERE nid=%d', $node->nid);
168 break;
169
170 case 'prepare':
171 // Book pages, set the right language nodes and outlines.
172 if (arg(3) == 'parent' && is_numeric(arg(4)) && ($parent = node_load(arg(4))) && $parent->language) {
173 $node->language = $parent->language;
174 i18n_selection_mode('node', $parent->language);
175 }
176 break;
177 }
178 }
179 }*/
180
181 /**
182 * Implementation of hook_alter_translation_link().
183 *
184 * Handles links for extended language. The links will have current language.
185 */
186 function i18n_translation_link_alter(&$links, $path) {
187 global $language;
188
189 // Check for a node related path, and for its translations.
190 if ((preg_match("!^node/([0-9]+)(/.+|)$!", $path, $matches)) && ($node = node_load((int)$matches[1])) && !empty($node->tnid)) {
191 $languages = language_list();
192 $extended = array();
193 foreach (translation_node_get_translations($node->tnid) as $langcode => $translation_node) {
194 if (!isset($links[$langcode]) && isset($languages[$langcode])) {
195 $extended[$langcode] = array(
196 'href' => 'node/'. $translation_node->nid . $matches[2],
197 'language' => $language,
198 'language_icon' => $languages[$langcode],
199 'title' => $languages[$langcode]->native,
200 'attributes' => array('class' => 'language-link'),
201 );
202 }
203 }
204 // This will run after languageicon module, so we add icon in case that one is enabled.
205 if ($extended && function_exists('languageicons_translation_link_alter')) {
206 languageicons_translation_link_alter($extended, $path);
207 }
208 $links = array_merge($links, $extended);
209 }
210 }
211
212 /**
213 * Implementation of hook_link_alter().
214 *
215 * Handles links for extended languages. Sets current interface language.
216 */
217 function i18n_link_alter(&$links, $node) {
218 global $language;
219
220 if ($node->tnid) {
221 foreach (array_keys(i18n_language_list('extended')) as $langcode) {
222 $index = 'node_translation_'. $langcode;
223 if (!empty($links[$index])) {
224 $links[$index]['language'] = $language;
225 }
226 }
227 }
228 }
229
230 /**
231 * Implementation of hook_user().
232 *
233 * Switch to user's language after login.
234 */
235 function i18n_user($op, &$edit, &$account, $category = NULL) {
236 if ($op == 'login' && $account->language) {
237 $_SESSION['language'] = $account->language;
238 i18n_get_lang($account->language);
239 }
240 }
241
242 /**
243 * Simple i18n API
244 */
245
246 /**
247 * Get language properties.
248 *
249 * @param $code
250 * Language code.
251 * @param $property
252 * It may be 'name', 'native', 'ltr'...
253 */
254 function i18n_language_property($code, $property) {
255 $languages = language_list();
256 return isset($languages[$code]->$property) ? $languages[$code]->$property : NULL;
257 }
258
259 /**
260 * Get node language.
261 */
262 function i18n_node_get_lang($nid, $default = '') {
263 $lang = db_result(db_query('SELECT language FROM {node} WHERE nid = %d', $nid));
264 return $lang ? $lang : $default ;
265 }
266
267 /**
268 * Get allowed languages for node.
269 *
270 * This allows node types to define its own language list implementing hook 'language_list'.
271 *
272 * @param $node
273 * Node to retrieve language list for.
274 * @param $translate
275 * Only languages available for translation. Filter out existing translations.
276 */
277 function i18n_node_language_list($node, $translate = FALSE) {
278 // Check if the node module manages its own language list.
279 $languages = node_invoke($node, 'language_list', $translate);
280 if (!$languages) {
281 if (variable_get('i18n_node_'. $node->type, 0) == LANGUAGE_SUPPORT_EXTENDED) {
282 $languages = locale_language_list('name', TRUE); // All defined languages
283 }
284 else {
285 $languages = locale_language_list(); // All enabled languages
286 }
287 if ($translate && isset($node->tnid) && $node->tnid && ($translations = translation_node_get_translations($node->tnid))) {
288 unset($translations[$node->language]);
289 foreach (array_keys($translations) as $langcode) {
290 unset($languages[$langcode]);
291 }
292 }
293 $languages = array('' => t('Language neutral')) + $languages;
294 }
295
296 return $languages;
297 }
298
299 /**
300 * Function i18n_get_links().
301 *
302 * Returns an array of links for all languages, with or without names/flags.
303 *
304 * @param $path
305 * Drupal internal path.
306 * @param $query
307 * Query string.
308 * @param $names
309 * Names to use for the links. Defaults to native language names.
310 */
311 function i18n_get_links($path = '', $query = NULL, $names = NULL) {
312 if ($path == variable_get('site_frontpage', 'node')) {
313 $path = '';
314 }
315 $names = $names ? $names : locale_language_list('native');
316 foreach (array_keys(i18n_supported_languages()) as $lang) {
317 $links[$lang] = theme('i18n_link', $names[$lang], i18n_path($path, $lang), $lang, $query);
318 }
319 return $links;
320 }
321
322 /**
323 * Selection mode for content.
324 *
325 * Warning: when used with params they need to be escaped, as some values are thrown directly in queries.
326 *
327 * Allows several modes for query rewriting and to change them programatically.
328 * off = No language conditions inserted.
329 * simple = Only current language and no language.
330 * mixed = Only current and default languages.
331 * strict = Only current language.
332 * default = Only default language.
333 * user = User defined, in the module's settings page.
334 * params = Gets the stored params.
335 * reset = Returns to previous.
336 * custom = add custom where clause, like "%alias.language = 'en'".
337 */
338 function i18n_selection_mode($mode = NULL, $params = NULL) {
339 static $current_mode = NULL;
340 static $current_value = '';
341 static $store = array();
342
343 // Initialization, first time this runs with no explicit mode.
344 if (!$current_mode && !$mode) {
345 $current_mode = variable_get('i18n_selection_mode', 'simple');
346 if ($current_mode != 'off') {
347 // Node language when loading specific nodes or creating translations.
348 if (arg(0) == 'node' ) {
349 if (($node = menu_get_object('node')) && $node->language) {
350 $current_mode = 'node';
351 $current_value = $node->language;
352 }
353 elseif (arg(1) == 'add' && !empty($_GET['translation']) && !empty($_GET['language']) && empty($_POST)) {
354 $current_mode = 'translation';
355 $current_value = db_escape_string($_GET['language']);
356 }
357 }
358 elseif (arg(0) == 'admin') {
359 // There are some exceptions for admin pages.
360 if (arg(1) == 'content' && user_access('administer all languages')) {
361 // No restrictions for administration pages.
362 $current_mode = 'off';
363 }
364 elseif (arg(1) == 'build' && arg(2) == 'menu-customize') {
365 // All nodes available when editing custom menu items.
366 $current_mode = 'off';
367 }
368 }
369 }
370 }
371
372 if (!$mode) {
373 return $current_mode;
374 }
375 elseif ($mode == 'params') {
376 return $current_value;
377 }
378 elseif ($mode == 'reset') {
379 list($current_mode, $current_value) = array_pop($store);
380 }
381 else {
382 array_push($store, array($current_mode, $current_value));
383 $current_mode = $mode;
384 $current_value = $params;
385 }
386 }
387
388 /**
389 * Implementation of hook_db_rewrite_sql().
390 *
391 * Rewrite node queries so language selection options are enforced.
392 */
393 function i18n_db_rewrite_sql($query, $primary_table, $primary_key, $args = array()) {
394 // If mode is 'off' = no rewrite, we cannot return any empty 'where' string so check here.
395 $mode = i18n_selection_mode();
396 if ($mode == 'off') return;
397
398 // Disable language conditions for views.
399 if (array_key_exists('view', $args)) return;
400
401 switch ($primary_table) {
402 case 'n':
403 case 'node':
404 // No rewrite for queries with subselect ? (views count queries).
405 // @ TO DO Actually these queries look un-rewrittable, check with other developers.
406 if (preg_match("/FROM \(SELECT/", $query)) return;
407 // No rewrite for translation module queries.
408 if (preg_match("/.*FROM {node} $primary_table WHERE.*$primary_table\.tnid/", $query)) return;
409 // When loading specific nodes, language conditions shouldn't apply.
410 if (preg_match("/WHERE.*\s$primary_table.nid\s*=\s*(\d|%d)/", $query)) return;
411 // If language conditions already there, get out.
412 if (preg_match("/i18n/", $query)) return;
413
414
415 // Mixed mode is a bit more complex, we need to join in one more table
416 // and add some more conditions, but only if language is not default.
417 if ($mode == 'mixed' && i18n_get_lang() != i18n_default_language()) {
418 $result['join'] = "LEFT JOIN {node} i18n ON $primary_table.tnid = i18n.tnid AND i18n.language = '". i18n_get_lang() ."'";
419 $result['where'] = i18n_db_rewrite_where($primary_table, 'node', 'simple');
420 // So we show also nodes that have default language.
421 $result['where'] .= " OR ($primary_table.language = '". i18n_default_language() ."' AND i18n.nid IS NULL)";
422 }
423 else {
424 $result['where'] = i18n_db_rewrite_where($primary_table, 'node', $mode);
425 }
426 return $result;
427 }
428 }
429
430 /**
431 * Rewrites queries depending on rewriting mode.
432 */
433 function i18n_db_rewrite_where($alias, $type, $mode = NULL) {
434 if (!$mode) {
435 // Some exceptions for query rewrites.
436 $mode = i18n_selection_mode();
437 }
438
439 // Get languages to simplify query building.
440 $current = i18n_get_lang();
441 $default = i18n_default_language();
442
443 if ($mode == 'strict' && $type != 'node') {
444 // Special case. Selection mode is 'strict' but this should be only for node queries.
445 $mode = 'simple';
446 }
447 elseif ($mode == 'mixed' && $current == $default) {
448 // If mode is mixed but current = default, is the same as 'simple'.
449 $mode = 'simple';
450 }
451
452 switch ($mode) {
453 case 'off':
454 return '';
455
456 case 'simple':
457 return "$alias.language ='$current' OR $alias.language ='' OR $alias.language IS NULL" ;
458
459 case 'mixed':
460 return "$alias.language ='$current' OR $alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;
461
462 case 'strict':
463 return "$alias.language ='$current'" ;
464
465 case 'node':
466 case 'translation':
467 return "$alias.language ='". i18n_selection_mode('params') ."' OR $alias.language ='' OR $alias.language IS NULL" ;
468
469 case 'default':
470 return "$alias.language ='$default' OR $alias.language ='' OR $alias.language IS NULL" ;
471
472 case 'custom':
473 return str_replace('%alias', $alias, i18n_selection_mode('params'));
474 }
475 }
476
477 /**
478 * Implementation of hook_exit().
479 */
480 function i18n_exit() {
481 _i18n_variable_exit();
482 }
483
484 /**
485 * Implementation of hook_form_alter();
486 *
487 * This is the place to add language fields to all forms.
488 */
489 function i18n_form_alter(&$form, $form_state, $form_id) {
490 switch ($form_id) {
491 case 'node_type_form':
492 // Add extended language support option to content type form.
493 $form['workflow']['i18n_node'] = array(
494 '#type' => 'radios',
495 '#title' => t('Extended language support'),
496 '#default_value' => variable_get('i18n_node_'. $form['#node_type']->type, LANGUAGE_SUPPORT_NORMAL),
497 '#options' => _i18n_content_language_options(),
498 '#description' => t('If enabled, all defined languages will be allowed for this content type in addition to only enabled ones. This is useful to have more languages for content than for the interface.')
499 );
500 break;
501
502 default:
503 // Extended language for node edit form.
504 if (isset($form['#id']) && $form['#id'] == 'node-form') {
505 if (isset($form['#node']->type) && variable_get('language_content_type_'. $form['#node']->type, 0)) {
506 $form['language']['#options'] = i18n_node_language_list($form['#node'], TRUE);
507 }
508 }
509 /** @ TO DO Upgrade
510 if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id && $node = $form['#node']) {
511 // Language field
512 if (variable_get('i18n_node_'.$form['type']['#value'], 0) && !isset($form['i18n']['language'])) {
513 // Language field
514 $form['i18n'] = array(
515 '#type' => 'fieldset',
516 '#title' => t('Multilingual settings'),
517 '#collapsible' => TRUE,
518 '#collapsed' => FALSE,
519 '#weight' => -4
520 );
521 // Language will default to current only when creating a node.
522 $language = isset($form['#node']->language) ? $form['#node']->language : (arg(1)=='add' ? i18n_get_lang() : '');
523 $form['i18n']['language'] = _i18n_language_select($language, t('If you change the language, you must click on <i>Preview</i> to get the right categories &amp; terms for that language.'), -4, i18n_node_language_list($node));
524 $form['i18n']['trid'] = array(
525 '#type' => 'value',
526 '#value' => $form['#node']->trid
527 );
528 }
529 // Correction for lang/node/nid aliases generated by path module.
530 // if ($form['#node']->path && $form['#node']->path == i18n_get_lang().'/node/'.$form['#node']->nid) {
531 if ($node->path) {
532 $alias = drupal_lookup_path('alias', 'node/'.$node->nid);
533 if($alias && $alias != 'node/'.$node->nid) {
534 $form['#node']->path = $alias;
535 }
536 else {
537 unset($form['#node']->path);
538 }
539 }
540 }
541 */
542 // Multilingual variables in settings form.
543 if (isset($form['#theme']) && $form['#theme'] == 'system_settings_form' && $variables = variable_get('i18n_variables', 0)) {
544 if (i18n_form_alter_settings($form, $variables)) {
545 $form['#submit'][] = 'i18n_variable_form_submit';
546 }
547 }
548 }
549 }
550
551 /**
552 * Implementation of hook_perm().
553 *
554 * Permissions defined
555 * - administer all languages
556 * Disables language conditions for administration pages, so the user can view objects for all languages at the same time.
557 * This applies for: menu items, taxonomy
558 */
559 function i18n_perm() {
560 return array('administer all languages');
561 }
562
563 /**
564 * Process menu and menu item add/edit form submissions.
565 */
566 function i18n_menu_edit_item_form_submit($form, &$form_state) {
567 $mid = menu_edit_item_save($form_state['values']);
568 db_query("UPDATE {menu} SET language = '%s' WHERE mid = %d", $form_state['values']['language'], $mid);
569 return 'admin/build/menu';
570 }
571
572 /**
573 * Check for multilingual variables in form.
574 */
575 function i18n_form_alter_settings(&$form, &$variables) {
576 $result = 0;
577 foreach (element_children($form) as $field) {
578 if (isset($form[$field]['#type']) && $form[$field]['#type'] == 'fieldset') {
579 $result += i18n_form_alter_settings($form[$field], $variables);
580 }
581 elseif (in_array($field, $variables)) {
582 $form[$field]['#description'] .= ' <strong>'. t('This is a multilingual variable.') .'</strong>';
583 $result++;
584 }
585 }
586 return $result;
587 }
588
589 /**
590 * Save multilingual variables and remove them from form.
591 */
592 function i18n_variable_form_submit($form, &$form_state) {
593 $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
594 $variables = variable_get('i18n_variables', array());
595 $language = i18n_get_lang();
596 foreach ($form_state['values'] as $key => $value) {
597 if (in_array($key, $variables)) {
598 if ($op == t('Reset to defaults')) {
599 i18n_variable_del($key, $language);
600 }
601 else {
602 if (is_array($value) && isset($form_state['values']['array_filter'])) {
603 $value = array_keys(array_filter($value));
604 }
605 i18n_variable_set($key, $value, $language);
606 }
607 unset($form_state['values'][$key]);
608 }
609 }
610 // Re-submit form
611 // system_settings_form_submit($form_id, $form_values);
612 }
613
614 /**
615 * Initialization of multilingual variables.
616 *
617 * @param $language
618 * Language to retrieve variables. Defaults to current language.
619 * @param $prefix
620 * Variable name prefix to load just a selected group of variables.
621 */
622 function i18n_variable_init($langcode = NULL, $prefix = '') {
623 global $conf;
624 global $i18n_conf;
625
626 $langcode = $langcode ? $langcode : i18n_get_lang();
627 if ($i18n_variables = variable_get('i18n_variables', '')) {
628 if (!$i18n_conf) {
629 $i18n_conf = array();
630 }
631 $variables = _i18n_variable_init($langcode, $prefix);
632 foreach ($i18n_variables as $name) {
633 $i18n_conf[$name] = isset($variables[$name]) ? $variables[$name] : (isset($conf[$name]) ? $conf[$name] : '');
634 }
635
636 $conf = array_merge($conf, $i18n_conf);
637 }
638 }
639
640 /**
641 * Helper function to create language selector.
642 */
643 function _i18n_language_select($value ='', $description ='', $weight = -20, $languages = NULL) {
644 $languages = $languages ? $languages : locale_language_list();
645 return array(
646 '#type' => 'select',
647 '#title' => t('Language'),
648 '#default_value' => $value,
649 '#options' => array_merge(array('' => ''), $languages),
650 '#description' => $description,
651 '#weight' => $weight,
652 );
653 }
654
655 /**
656 * Load language variables into array.
657 */
658 function _i18n_variable_init($language, $prefix = '') {
659 $variables = array();
660 $cacheid = 'variables:'. $language . ($prefix ? ':'. $prefix : '');
661 if ($cached = cache_get($cacheid)) {
662 $variables = $cached->data;
663 }
664 else {
665 $result = db_query("SELECT * FROM {i18n_variable} WHERE language='%s' AND name LIKE '%s%'", $language, $prefix);
666 while ($variable = db_fetch_object($result)) {
667 $variables[$variable->name] = unserialize($variable->value);
668 }
669 cache_set($cacheid, $variables);
670 }
671 return $variables;
672 }
673
674 /**
675 * Save multilingual variables that may have been changed by other methods than settings pages.
676 */
677 function _i18n_variable_exit() {
678 global $i18n_conf;
679 global $conf;
680 if ($i18n_conf) {
681 $lang = i18n_get_lang();
682 $refresh = FALSE;
683 // Rewritten because array_diff_assoc may fail with array variables.
684 foreach ($i18n_conf as $name => $value) {
685 if ($value != $conf[$name]) {
686 $refresh = TRUE;
687 $i18n_conf[$name] = $conf[$name];
688 db_query("DELETE FROM {i18n_variable} WHERE name='%s' AND language='%s'", $name, $lang );
689 db_query("INSERT INTO {i18n_variable} (language, name, value) VALUES('%s', '%s', '%s')", $lang, $name, serialize($conf[$name]));
690 }
691 }
692 if ($refresh) {
693 cache_set('variables:'. $lang, $i18n_conf);
694 }
695 }
696 }
697
698 /**
699 * Check whether we are in bootstrap mode
700 */
701 function _i18n_is_bootstrap() {
702 return !function_exists('drupal_get_headers');
703 }
704
705 /**
706 * Drupal 6, backwards compatibility layer
707 * @ TO DO Fully upgrade all the modules and remove
708 */
709
710 /**
711 * This one expects to be called first from common.inc
712 */
713 function i18n_get_lang() {
714 global $language;
715 return $language->language;
716 }
717
718 /**
719 * @defgroup i18n_api Extended language API
720 * @{
721 * This is an extended language API to be used by modules in i18n package.
722 */
723
724 /**
725 * Returns language lists
726 */
727 function i18n_language_list($type = 'enabled', $field = 'name') {
728 switch ($type) {
729 case 'enabled':
730 return locale_language_list($field);
731
732 case 'extended':
733 $enabled = locale_language_list($field);
734 $defined = locale_language_list($field, TRUE);
735 return array_diff_assoc($defined, $enabled);
736 }
737 }
738
739 /**
740 * Returns default language code.
741 */
742 function i18n_default_language() {
743 return language_default('language');
744 }
745
746 /**
747 * Get list of supported languages, native name.
748 *
749 * @param $all
750 * TRUE to get all defined languages.
751 */
752 function i18n_supported_languages($all = FALSE) {
753 return locale_language_list('native', $all);
754 }
755
756 /**
757 * Set a persistent language dependent variable.
758 *
759 * @param $name
760 * The name of the variable to set.
761 * @param $value
762 * The value to set. This can be any PHP data type; these functions take care
763 * of serialization as necessary.
764 * @param $langcode
765 * Language code.
766 */
767 function i18n_variable_set($name, $value, $langcode) {
768 global $conf, $i18n_conf;
769
770 db_lock_table('i18n_variable');
771 db_query("DELETE FROM {i18n_variable} WHERE name = '%s' AND language='%s'", $name, $langcode);
772 db_query("INSERT INTO {i18n_variable} (name, language, value) VALUES ('%s', '%s', '%s')", $name, $langcode, serialize($value));
773 db_unlock_tables();
774
775 cache_clear_all('variables:'. $langcode, 'cache');
776
777 $conf[$name] = $value;
778 $i18n_conf[$name] = $value;
779 }
780
781 /**
782 * Unset a persistent multilingual variable.
783 *
784 * @param $name
785 * The name of the variable to undefine.
786 * @param $langcode
787 * Language code.
788 */
789 function i18n_variable_del($name, $langcode) {
790 global $conf, $i18n_conf;
791
792 db_query("DELETE FROM {i18n_variable} WHERE name = '%s' AND language='%s'", $name, $langcode);
793 cache_clear_all('variables:'. $langcode, 'cache');
794
795 unset($conf[$name]);
796 unset($i18n_conf[$name]);
797 }
798
799 /**
800 * Utility. Get part of array variable.
801 */
802 function i18n_array_variable_get($name, $element, $default = NULL) {
803 if (($values = variable_get($name, array())) && isset($values[$element])) {
804 return $values[$element];
805 }
806 else {
807 return $default;
808 }
809 }
810
811 /**
812 * Utility. Set part of array variable.
813 */
814 function i18n_array_variable_set($name, $element, $value) {
815 $values = variable_get($name, array());
816 $values[$element] = $value;
817 variable_set($name, $values);
818 }
819
820 /**
821 * @} End of "defgroup i18n_api".
822 */
823
824 /**
825 * List of language support modes for content.
826 */
827 function _i18n_content_language_options() {
828 return array(
829 LANGUAGE_SUPPORT_NORMAL => t('Normal - All enabled languages will be allowed.'),
830 LANGUAGE_SUPPORT_EXTENDED => t('Extended - All defined languages will be allowed.')
831 );
832 }