summaryrefslogtreecommitdiffstats
path: root/i18n.module
blob: d3c93a6fa192c8efe9826a164dece40379aac626 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
<?php
// $Id$

/**
 * Internationalization (i18n) module
 *
 * @author Jose A. Reyero, 2004
 *
 */

/**
 * Module initialization
 * 
 * Get language from path if exists and Initialize i18n system
 * 
 */

function i18n_init(){
  global $i18n_langpath;
  
  $path = i18n_get_original_path();
  $i18n_langpath = i18n_get_lang_prefix($path);
  $lang = _i18n_get_lang();
  
  
  if ($path == '') { // Main page
    if( variable_get('cache',0) && $lang != i18n_default_language() ) {
      // Redirect to main page in $lang
      drupal_goto($lang);
    } elseif (variable_get('i18n_frontpage',0)){
      $_GET['q'] = i18n_frontpage();
    } 
  } 
  elseif ($lang == $path) { // When path is only language code
    $_GET['q'] =  variable_get('i18n_frontpage',0) ? i18n_frontpage() : variable_get('site_frontpage','node'); 
  }
  elseif ($i18n_langpath) {
    //search alias with and without lang and remove lang
    $_GET['q'] = i18n_get_normal_path($path);
  } 

  // Multi table, for backwards compatibility and experimentation
  if (variable_get('i18n_multi' , 0)) {
    i18n_set_db_prefix(_i18n_get_lang());
  }

  // This function are only defined when module is enabled
  // Otherwise, it messes up the module administration menu
function i18n_url_rewrite($path, $mode ='outgoing') {
   if ($mode == 'outgoing' && !i18n_get_lang_prefix($path)) {
      return i18n_get_lang() . '/'. $path;
   } else {
     return $path;
   }
}  // End of i18n_url_rewrite  

/**
 * This one expects to be called first from common.inc
 * When first called, calls _i18n_init();
 */
function i18n_get_lang() {
  static $i18n_language;
  //see if the language is already set.
  if ($i18n_language) {
    return $i18n_language;
  } else {
    _i18n_init();
    return $i18n_language = _i18n_get_lang();
  }
}  // End of i18n_get_lang

}  // End of i18n_init    

/**
 * Check whether we are in bootstrap mode
 */  
function i18n_is_bootstrap(){
  return !function_exists('drupal_get_headers');
}    

/*
 * Second stage init, from common.inc
 * Does some additional includes
 */
function _i18n_init() {
  // Include parts, may be conditional include in the future
  include_once 'modules/i18n/i18n_node.inc';
  include_once 'modules/i18n/i18n_taxonomy.inc';  
}
/**
 *  Common module functions
 */

/**
 * Implementation of hook_help().
 */
function i18n_help($section = 'admin/help#i18n' ) {
  switch ($section) {
    case 'admin/help#i18n' :
      $output = t('
      	<p><strong>To be rewritten</strong></p>
        <p>This module provides support for internationalization of Drupal sites:</p>
        <ul><li>Translation of the user interface for anonymous users (combined with locale)</li>
        <li>Multi-language for content. Adds a language field for nodes and taxonomy terms</li>
        <li>Basic translation management</li>
        <li>Browser language detection</li>
        <li>Keeps the language setting accross consecutive requests, using URL rewriting</li>
        <li>Provides a block for language selection and two theme functions: <i>i18n_flags</i> and <i>i18n_links</i></li></ul>
        <p><small>Module developed by <a href="http://freelance.reyero.net">freelance.reyero.net</a></small></p>' );
      break;
  case 'admin/modules#description' :
    $output = t('Enables multilingual content. <b>Requires locale module for interface translation</b>' );
    break;
  }
  return $output;
}

/**
 * Implementation of hook_settings().
 */
function i18n_settings() {
  global $db_prefix_i18n;
  
  // Basic settings

  $output .= form_radios(t('Supported languages'), 'i18n_supported_langs' , variable_get('i18n_supported_langs', 'i18n'), 
    array(
      'i18n'  => t('Defined in the configuration file ($i18n_languages)'), 
      'locale' => t('Defined by the locale module')
    ), t('Where to get the list of supported languages from' ));
  /* Disabled
  $output .= form_radios(t('Simple content translation"), "i18n_content", variable_get("i18n_content", 0), array(t("Disabled"), t("Enabled")), t(' If enabled, prepends language code to url and searches for translated content. <strong>Requires url aliasing with 'path' module.</strong>"));
  */
  $output .= form_radios(t('Browser language detection'), 'i18n_browser', variable_get('i18n_browser', 0), array(t('Disabled'), t('Enabled' )));
  $output .= form_select(t('Front page'), 'i18n_frontpage', variable_get('i18n_frontpage', 0), array(t('Default'), t('Language dependent')), t(" If 'language dependent' is selected, default front page will be prepended with language code, i.e. 'en/node'"));

  $output .= form_textfield(t('Language icons html tag'), 'i18n_flags', variable_get('i18n_flags', '<img class="i18n-flag" src="modules/i18n/flags/*.png" width="16" height="12"/>'), 70, 180, 
    t('HTML tag for flags. Asterisk \'*\' is a placeholder for language code. It should be something like &lt;img class="i18n-flag" src="modules/i18n/flags/*.png" width="16" height="12"/&gt'));

  $output .= t('<h2>Multilingual content</h2>' );
  foreach (node_list() as $node) {
    $subform.=form_checkbox(t($node), 'i18n_node_'.$node, 1, variable_get('i18n_node_'.$node, 0));
  }   
  $output .= form_group(t('Nodes' ), $subform, t('Select node types to be translated.' ));
  
  $output .= t('<h2>Advanced Features</h2>' );
  $output .= t('<p>These are intended only for advanced users. Some changes to the database are required. Please, do read the INSTALL.txt and README.txt files before enabling these options</p>' );

  // Advanced features
  // Language dependent tables
  if (is_array($db_prefix_i18n)) {
    $multi=true;
    $text = '<strong>'.t('Current language dependent tables are: '). implode(', ', array_keys($db_prefix_i18n)).'</strong>' ;
  }  else {
    $text = t("Check the module's SETUP.txt file.");
  }
  $output .= form_radios(t('Language dependent tables'), 'i18n_multi', variable_get('i18n_multi', 0), array(t('Disabled'), t('Enabled')), t('If enabled, different tables for each language will be used. They must be defined in the configuration file.') . ' ' . $text);
 
  return $output;
}

/**
 * Implementation of hook_menu().
 */
function i18n_menu($may_cache) {
  $items = array();

  if ($may_cache) {
      $items[] = array(
        'path' => 'translation',
        'title' => t('translation'),
        'callback' => 'i18n_translation_page',
        'access' => user_access('administer nodes'),
        'type' => MENU_CALLBACK);
      /* Disabled term translations
      $items[] = array(
        'path' => 'admin/taxonomy/i18n', 
        'title' => t('translation'),
        'callback' => 'i18n_taxonomy_admin',
        'access' => user_access('administer taxonomy'),
        'type' => MENU_LOCAL_TASK);
     */
  }
  else {
    if (arg(0) == 'node' && is_numeric(arg(1)) && variable_get('i18n_node_'.i18n_get_node_type(arg(1)), 0)) {
      $access = user_access('administer nodes');
      $type = MENU_LOCAL_TASK;      
      $items[] = array(
        'path' => 'node/'. arg(1) .'/translation', 
        'title' => t('translation'),
        'callback' => 'i18n_node_translation',
        'access' => $access,
        'type' => $type);
    }
  }

  return $items;
} // End of i18n_menu

// translation/node/id/lang
// translation/term/id

function i18n_translation_page() {
  $op = $_POST['op'] ? $_POST['op'] : arg(1);
  $edit = $_POST['edit'];
  
  switch ($op) {
    case 'node':
      print theme('page', i18n_translation_add(arg(2), arg(3)));
      break;
      
     case t('Preview'):
      $edit = node_validate($edit);
      print theme('page', node_preview($edit), t('Preview'));
      break;
      
    case t('Submit'):
      drupal_set_title(t('Submit'));
      print theme('page', node_submit($edit));
      break;
      
    case t('Delete'):
      print theme('page', node_delete($edit), t('Delete'));
      break;
      
    default:
      // print theme('page', node_page_default(), '');
  }      
}

function i18n_translation_add($nid, $lang) {
  $type = i18n_get_node_type($nid);
  return node_add($type);
}

/**
 * Implementation of hook_link().
 */


function i18n_link($type, $node = NULL, $teaser = FALSE) {
  $links = array();
  if ($type == 'node' && !$teaser && variable_get('i18n_node_'.$node->type, 0)) {
    $languages = i18n_supported_languages();
    $translations = i18n_node_get_translations($node->nid);
    foreach ($translations as $lang => $trnode) {
        $links[]= theme('i18n_link_name_flag', $lang, 'node/'. $trnode->nid);
     }
  }
  return $links;
}


function i18n_block($op = 'list', $delta = 0) {
  if ($op == 'list') {
  $blocks[0]['info'] = t('Languages');
  }
  else {
    $blocks['subject'] = t('Languages');
    $content = '<table><tr><td>' ;
    $content .=  theme('i18n_links', 1, 1, '</td><td>', '</td></tr><tr><td>' );
    $content .= '</td></tr></table>' ;
  $blocks['content'] =$content;
  }

  return $blocks;
}


/**
 * i18n api
 */


/**
 *	Gets language, checking in order:
 *
 *	1. Path language
 *	2. User language
 *	3. Browser language
 *	4. Default language
 */

function _i18n_get_lang() {
  global $user, $i18n_langpath;
  static $i18n_lang;
  
  //see if the language is already set.
  if ($i18n_lang) {
    return $i18n_lang;
  }

  $languages = i18n_supported_languages();
   
  if ($i18n_langpath && array_key_exists($i18n_langpath,$languages)) {
    $i18n_lang = $i18n_langpath;
  }
  elseif ($user->uid && $user->language && array_key_exists($user->language,$languages)) {
    $i18n_lang = $user->language;
  }
  elseif (variable_get("i18n_browser",0) && $lang=i18n_get_browser_lang()) {
    $i18n_lang=$lang;
  }
  else {
    $i18n_lang=key($languages);
  }
  
  return $i18n_lang;
}

/**
 * Get list of supported languages
 */
function i18n_supported_languages() {
  global $i18n_languages;  
  static $languages;
  if ($languages) {
    return $languages;
  }
  elseif (variable_get('i18n_supported_langs', 'i18n') == 'locale') {
    $languages = i18n_locale_supported_languages();
    return $languages;
  } 
  elseif (is_array($i18n_languages)) {
    return $languages = $i18n_languages;
  } 
  else {
    return array();
  }
} 

/**
 * Returns default language
 */
function i18n_default_language(){
  return key(i18n_supported_languages());
}

/**
 * Returns list of enabled languages from locale module
 *
 * * Some code borrowed from locale module
 */
function i18n_locale_supported_languages() {
  $enabled = array();
  $result = db_query('SELECT locale, name FROM {locales_meta} WHERE enabled = 1 ORDER BY isdefault DESC, name ASC');
  while ($row = db_fetch_object($result)) {
    $enabled[$row->locale] = $row->name;
  }
  return $enabled;
}


/**
 * To get the original path. 
 * Cannot use $_GET["q"] cause it may have been already changed
 */
function i18n_get_original_path() {
  return isset($_REQUEST["q"]) ? trim($_REQUEST["q"],"/") : '';
}

// Get language from browser settings, but only if it is in the $i18n_languages array
function i18n_get_browser_lang() {
  $languages = i18n_supported_languages();
  $accept=explode(',',array_shift( explode(";",$_SERVER["HTTP_ACCEPT_LANGUAGE"])));
  foreach ($accept as $lang) {
    $lang=substr($lang,0,2);
    if ( !empty($lang) && array_key_exists($lang,$languages)) {
      return $lang;
    }
  }
}

/**
 * @name Theme functions
 * @{
 */
 
/**
  * Returns language links with optional flags
  *
  * @param $flags an integer, 1 to use language flags
  * @param $names an integer, 1 to use language names
  * @param $delim1 delimiter to place between language name and flag
  * @param $delim2 delimiter to place between different languages
  *
  * @return a string containing the @a links output.
  */
  
function theme_i18n_links($flags = 1, $names = 1, $delim1 = ' ' , $delim2 = ' ' ) {
  $i18n_lang = i18n_get_lang();
  $languages = i18n_supported_languages();
  foreach ($languages as $lang => $langname) {
    $name = $names ? t($langname): '' ; // Should be localized??
    $flag= $flags ? i18n_flag($lang) : '' ;
    if ($lang == $i18n_lang) {
      $links[] = "<strong>$name</strong>$delim1$flag";
    }
    else {
      $links[] = i18n_l($name, $lang).$delim1.i18n_l($flag, $lang);
    }
  }
  $output =implode($delim2, $links);
  return $output;  
}

function theme_i18n_flags() {
  return theme_i18n_links(1, 0);
}

function theme_i18n_link_name_flag($lang, $path, $attributes = array()) {
  static $languages;
  if (!isset($languages)) {
    $languages = i18n_supported_languages();
  }
  return '<span class="i18n-link">'. l(t($languages[$lang]), $path, $attributes) . '&nbsp;' . l(i18n_flag($lang) , $path, $attributes) .'</span>';
}


/*
 * Creates links for different languages
 */
 
function i18n_l($text, $lang , $url = '' , $attributes = array(), $query = NULL) {
  global $i18n_langpath;
  // If !url get from original request
  if (!$url) {
    $url = i18n_get_original_path();
  }
    // If url has lang_prefix, remove it
  if (i18n_get_lang_prefix($url)) {
    $url = substr($url, 3);
  }
 // $result= l($text, $url, $attributes, $query);
  return '<a href="'. i18n_url($url, $lang, $query) .'"'. drupal_attributes($attributes) .'>'. $text .'</a>';
}

function i18n_url($url, $lang, $query = NULL) {
  if ($url) {
    return url($lang.'/'.$url, $query);
  } else {
    return url($lang,$query);
  }
}

function i18n_flag($lang, $attribs = array()) {
  if ($path = variable_get('i18n_flags', '<img class="i18n-flag" src="modules/i18n/flags/*.png" width="16" height="12"/>')) {
    $flag = str_replace('*' , $lang, $path);
    if(!empty($attribs)){
      $flag = str_replace('<','< '.drupal_attributes($attribs).' ',$flag);
    }
		return $flag;
  }
}
/* @} */


/**
 * Manage language dependent variables
 *
 * Requires a patch in bootstrap.inc
 */
function i18n_variable($name) {
  global $i18n_variables;
  if (is_array($i18n_variables) and in_array($name, $i18n_variables)) {
    return i18n_get_lang().'_'.$name ;
  } else {
    return $name;
  }
}

/**
 * Get language code from path.
 *
 * It doesn't check anymore for valid languages, so any two letter code at the beginning of the path will be taken as a lang code
 */
function i18n_get_lang_prefix($path) {
  if (preg_match("/^\w\w($|\/.*)/", $path)) {
    return substr($path, 0, 2);
  }
}

/**
 * Sets db_prefix to given language
 */
function i18n_set_db_prefix($lang) {
  global $db_prefix, $db_prefix_i18n;
  if (is_array($db_prefix_i18n)) {
    $db_prefix = array_merge($db_prefix, str_replace('**', $lang, $db_prefix_i18n));
  }
}

/**
 * Language dependent front page
 */
function i18n_frontpage() {
  $path = _i18n_get_lang().'/'.variable_get('site_frontpage','node');
  return i18n_get_normal_path($path);
}

/**
 * This function is similar to drupal_get_normal_path, but language-aware
 * Also removes language from path
 */
function i18n_get_normal_path($path) {
  // First, check alias with lang
  if (($map = drupal_get_path_map()) && isset($map[$path])) {
    return $map[$path];
  } elseif (i18n_get_lang_prefix($path)) {
    // Check alias without lang
    $path = trim(substr($path,3),'/');
    if( isset($map[$path])) {
      return $map[$path];
    } 
  } 
  // We only get here when no alias is defined, with or without lang
  return $path;
}

?>