5 * Internationalization (i18n) module
7 * These are the functions to be defined only when module is enabled.
8 * Otherwise they could mess up with the admin system
10 * @author Jose A. Reyero, 2004
15 * Implementation of conf_url_rewrite
17 * This is a conditional definition, just in case it is defined somewhere else
20 if(!function_exists('custom_url_rewrite')) {
21 function custom_url_rewrite($type, $path, $original) {
22 return i18n_url_rewrite($type, $path, $original);
26 function i18n_url_rewrite($type, $path, $original){
27 if ($type == 'alias' && !i18n_get_lang_prefix($path) ){
28 return $path ?
i18n_get_lang() .
'/'.
$path : i18n_get_lang();
35 * Implementation of hook_db_rewrite_sql()
37 function i18n_db_rewrite_sql($query, $primary_table, $primary_key){
38 // Some exceptions for query rewrites
39 if(strstr(request_uri(),'cron.php')) return;
41 $alias = $primary_table;
45 $result = i18n_db_node_rewrite($query, $primary_table, $primary_key);
49 $result = i18n_db_taxonomy_rewrite($query, $primary_table, $primary_key);
56 function i18n_db_node_rewrite($query, $primary_table, $primary_key){
57 $alias = $primary_table;
58 // When loading specific nodes, language conditions shouldn't apply
59 // TO-DO: Refine this regexp
60 if (preg_match("/WHERE.*$alias.nid\s*=\s*(\d|%d)/", $query)) return;
61 //drupal_set_message($query);
62 $mode = i18n_selection_mode();
63 if($mode == 'off') return;
65 $result['join'] = "LEFT JOIN {i18n_node} i18n ON $alias.nid = i18n.nid";
70 $result['where'] = "$alias.language ='".
i18n_get_lang().
"' OR $alias.language IS NULL" ;
73 $result['where'] = "$alias.language ='".
i18n_get_lang().
"' OR $alias.language ='".
i18n_default_language().
"' OR $alias.language IS NULL" ;
76 $result['where'] = "$alias.language ='".
i18n_get_lang().
"'" ;
79 $result['where'] = "$alias.language ='".
i18n_default_language().
"' OR $alias.language IS NULL" ;
86 function i18n_db_taxonomy_rewrite($query, $primary_table, $primary_key){
87 // When loading specific terms, vocabs, language conditions shouldn't apply
88 // TO-DO: Refine this regexp
89 if (preg_match("/WHERE.* $primary_table\.tid\s*(=\s*\d|IN)/", $query)) return;
91 // Decide language depending on what we are doing
92 $lang = i18n_get_lang(); // Default
95 $edit = $_POST['edit'];
98 $lang = isset($edit['language']) ?
$edit['language'] : i18n_get_lang();
99 } elseif( is_numeric(arg(1)) && arg(2) == 'edit') {
101 if(is_array($edit)) {
102 $lang = isset($edit['language']) ?
$edit['language'] : i18n_get_lang();
104 $lang = i18n_node_get_lang(arg(1), i18n_get_lang());
107 $lang = i18n_get_lang();
111 $edit = $_POST['edit'];
112 $lang = isset($edit['language']) ?
$edit['language'] : arg(3);
115 if(arg(1) == 'taxonomy') {
116 // Taxonomy administration. Show all
121 if(arg(1) == 'term'){
128 $alias = $primary_table;
129 $result['where'] = "$alias.language ='$lang' OR $alias.language = ''";
135 * Implementation of hook_exit
137 function i18n_exit(){
138 _i18n_variable_exit();
142 * Implementation of hook_form_alter
144 * This is the place to add language fields to all forms
145 * Alan: - changed to test in case translation_form_alter (or another module/mechanism) has already set language
146 * - translation module may reduce language selection options in case there already exist translations
148 function i18n_form_alter($form_id, &$form) {
149 //drupal_set_message("i18n_form_alter form_id=$form_id ");
151 case
'taxonomy_overview_vocabularies':
152 $vocabularies = taxonomy_get_vocabularies();
153 $languages = i18n_supported_languages();
154 foreach ($vocabularies as
$vocabulary) {
155 if($vocabulary->language
) $form[$vocabulary->vid
]['type']['#value'] = $form[$vocabulary->vid
]['type']['#value'].
' ('.
$languages[$vocabulary->language
].
')';
158 case
'taxonomy_form_vocabulary': // Taxonomy vocabulary
159 if(isset($form['vid'])) {
160 $vocabulary = taxonomy_get_vocabulary($form['vid']['#value']);
162 $form['language'] = _i18n_language_select(isset($vocabulary) ?
$vocabulary->language
: i18n_get_lang(),t('This language will be set for all terms in this vocabulary'));
165 case
'taxonomy_form_term': // Taxonomy term
166 if(isset($form['vid']) && is_numeric($form['vid'])) {
167 $vocabulary = taxonomy_get_vocabulary($form['vid']);
169 $form['language'] = _i18n_language_select(isset($vocabulary) ?
$vocabulary->language
: i18n_get_lang());
173 // Content type settings
174 if (isset($form['type']) && $form['type']['#value'] .
'_node_settings' == $form_id) {
175 $form['workflow']['i18n_node_'.
$form['type']['#value']] = array(
177 '#title' => t('Multilingual support'),
178 '#default_value' => variable_get('i18n_node_'.
$form['type']['#value'], 0),
179 '#options' => array(t('Disabled'), t('Enabled')),
180 '#description' => t('Enables language field and multilingual support for this content type.'),
184 if (isset($form['type']) && $form['type']['#value'] .
'_node_form' == $form_id){
186 if(variable_get('i18n_node_'.
$form['type']['#value'], 0) && !isset($form['i18n']['language'])) {
188 $form['i18n'] = array('#type' => 'fieldset', '#title' => t('Language'), '#collapsible' => TRUE
, '#collapsed' => FALSE
, '#weight' => -4);
189 // Language will default to current only when creating a node
190 $language = isset($form['#node']->language
) ?
$form['#node']->language
: (arg(1)=='add' ?
i18n_get_lang() : '');
191 $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 & Terms for that language.'), -4);
193 // Correction for lang/node/nid aliases generated by path module
194 // if($form['#node']->path && $form['#node']->path == i18n_get_lang().'/node/'.$form['#node']->nid){
195 if($form['#node']->path
) {
196 $alias=drupal_lookup_path('alias', 'node/'.
$form['#node']->nid
);
197 if($alias && $alias != 'node/'.
$form['#node']->nid
){
198 $form['#node']->path
= $alias;
200 unset($form['#node']->path
);
209 * Implementation of hook_nodeapi
210 * Updated for new table i18n_node
212 function i18n_nodeapi(&$node, $op, $teaser = NULL
, $page = NULL
) {
213 if (variable_get("i18n_node_$node->type", 0)) {
216 return db_fetch_array(db_query("SELECT trid, language FROM {i18n_node} WHERE nid=%d", $node->nid
));
219 db_query("DELETE FROM {i18n_node} WHERE nid=%d",$node->nid
);
221 db_query("INSERT INTO {i18n_node} (nid, trid, language) VALUES(%d, '%d', '%s')", $node->nid
, $node->trid
, $node->language
);
225 db_query('DELETE FROM {i18n_node} WHERE nid=%d', $node->nid
);
232 * Helper function to create language selector
234 function _i18n_language_select($value ='', $description ='', $weight = -20){
237 '#title' => t('Language'),
238 '#default_value' => $value,
239 '#options' => array_merge(array('' => ''), i18n_supported_languages()),
240 '#description' => $description,
241 '#weight' => $weight,
246 * Implementation of hook_taxonomy
248 * $edit parameter may be an array or an object !!
250 function i18n_taxonomy($op, $type, $edit = NULL
) {
251 $edit = (array)$edit;
252 switch ("$type/$op") {
255 $language = isset($edit['language']) ?
$edit['language'] : '';
256 db_query("UPDATE {term_data} SET language='%s' WHERE tid=%d", $language, $edit['tid']);
258 case
'vocabulary/insert':
259 case
'vocabulary/update':
260 $language = isset($edit['language']) ?
$edit['language'] : '';
261 db_query("UPDATE {vocabulary} SET language='%s' WHERE vid=%d", $language, $edit['vid']);
262 if ($language && $op == 'update') {
263 db_query("UPDATE {term_data} t SET t.language='%s' WHERE t.vid=%d", $edit['language'], $edit['vid']);
264 drupal_set_message(t('Reset language for all terms.'));
275 * This one expects to be called first from common.inc
277 function i18n_get_lang() {
278 static
$i18n_language;
279 //see if the language is already set.
280 if ($i18n_language) {
281 return $i18n_language;
283 return $i18n_language = _i18n_get_lang();
287 // Note: do not call url() anymore, it will be called from l()
288 function i18n_url($url, $lang) {
289 // Strip prefix if default language
291 return $lang.
'/'.
$url;
297 function i18n_node_get_lang($nid, $default = '') {
298 $lang = db_result(db_query('SELECT language FROM {i18n_node} WHERE nid=%d',$nid));
299 return $lang ?
$lang : $default ;
303 * Returns main language, two letter code
305 function i18n_get_main_lang($lang = NULL
){
306 $lang = $lang ?
$lang : i18n_get_lang();
307 return substr($lang, 2);
314 * This is a simple language switcher which knows nothing about translations
316 function i18n_block($op = 'list', $delta = 0) {
318 $blocks[0]['info'] = t('Language switcher');
320 elseif($op == 'view') {
321 $blocks['subject'] = t('Languages');
322 $blocks['content'] = theme('item_list', i18n_get_links($_GET['q']));
329 * Function i18n_get_links
331 * Returns an array of urls for all languages, with or without names/flags
333 function i18n_get_links($path = '') {
334 foreach(i18n_supported_languages() as
$lang => $name){
335 $links[$lang]= theme('i18n_link', $name, i18n_url($path, $lang), $lang);
342 * Multilingual variables
344 function i18n_variable_init(){
347 $lang = _i18n_get_lang();
348 if($i18n_variables = variable_get('i18n_variables', '')){
349 $i18n_conf = array();
350 $variables = _i18n_variable_init();
351 foreach($i18n_variables as
$name){
352 $i18n_conf[$name] = isset($variables[$name]) ?
$variables[$name] : (isset($conf[$name]) ?
$conf[$name] : '');
354 $conf = array_merge($conf, $i18n_conf);
358 function _i18n_variable_init(){
359 $lang = _i18n_get_lang();
360 $variables = array();
361 if ($cached = cache_get('variables:'.
$lang)) {
362 $variables = unserialize($cached->data
);
365 $result = db_query("SELECT * FROM {i18n_variable} WHERE language='%s'", $lang);
366 while ($variable = db_fetch_object($result)) {
367 $variables[$variable->name
] = unserialize($variable->value
);
369 cache_set('variables:'.
$lang, serialize($variables));
376 function _i18n_variable_exit(){
379 $lang = _i18n_get_lang();
381 $variables = array_diff_assoc($i18n_conf, $conf);
383 foreach($variables as
$name => $value){
384 $i18n_conf[$name] = $conf[$name];
385 db_query("DELETE FROM {i18n_variable} WHERE name='%s' AND language='%s'", $name, $lang );
386 db_query("INSERT INTO {i18n_variable} (language, name, value) VALUES('%s', '%s', '%s')", $lang, $name, serialize($conf[$name]));
388 cache_set('variables:'.
$lang, serialize($i18n_conf));
394 * @name Themeable functions
399 * Produces a language link with the right flag
401 function theme_i18n_link($text, $target, $lang, $separator=' '){
402 $output = '<span class="i18n-link">';
403 $attributes = ($lang == i18n_get_lang()) ?
array('class' => 'active') : NULL
;
404 $output .
= l(theme('i18n_language_icon', $lang), $target, $attributes, NULL
, NULL
, FALSE
, TRUE
);
405 $output .
= $separator;
406 $output .
= l($text, $target, $attributes, NULL
, NULL
, FALSE
, TRUE
);
407 $output .
= '</span>';
411 function theme_i18n_language_icon($lang){
412 if ($path = variable_get('i18n_icon_path', drupal_get_path('module', 'i18n').
'/flags/*.png')) {
413 $languages = i18n_supported_languages();
414 $src = base_path().
str_replace('*', $lang, $path);
415 list($width, $height) = explode('x', variable_get('i18n_flags_size', '16x12'));
416 $attribs = array('class' => 'i18n-icon', 'width' => $width, 'height' => $height, 'alt' => $languages[$lang]);
417 return "<img src=\"$src\" ".
drupal_attributes($attribs).
" />";