1<?php 2 /**************************************************************************\ 3 * phpGroupWare - Translation Editor * 4 * http://www.phpgroupware.org * 5 * -------------------------------------------- * 6 * This program is free software; you can redistribute it and/or modify it * 7 * under the terms of the GNU General Public License as published by the * 8 * Free Software Foundation; either version 2 of the License, or (at your * 9 * option) any later version. * 10 \**************************************************************************/ 11 12 /* $Id: class.solangfile.inc.php 16054 2005-08-12 13:50:23Z skwashd $ */ 13 14 class solangfile 15 { 16 var $total; 17 var $debug = False; 18 19 var $langarray; // Currently loaded translations 20 // array of missing phrases. 21 var $missingarray; 22 var $src_file; 23 var $tgt_file; 24 var $loaded_apps = array(); // Loaded app langs 25 26 var $functions = array( // functions containing phrases to translate and param# 27 'lang' => array(1), 28 'create_input_box' => array(1,3), 29 'create_check_box' => array(1,3), 30 'create_select_box' => array(1,4), 31 'create_text_area' => array(1,5), 32 'create_notify' => array(1,5), 33 'create_password_box' => array(1,3) 34 ); 35 var $files = array( 36 'config.tpl' => 'config', 37 'hook_admin.inc.php' => 'file_admin', 38 'hook_preferences.inc.php' => 'file_preferences', 39 'hook_sidebox_menu.inc.php' => 'file', 40 'hook_acl_manager.inc.php' => 'acl_manager' 41 ); 42 43 var $public_functions = array( 44 'index' => True 45 ); 46 47 function solangfile() 48 { 49 $this->db = $GLOBALS['phpgw']->db; 50 } 51 52 function fetch_keys($app,$arr) 53 { 54 if (!is_array($arr)) 55 { 56 return; 57 } 58 foreach($arr as $key => $val) 59 { 60 $this->plist[$key] = $app; 61 } 62 } 63 64 function config_file($app,$fname) 65 { 66 //echo "<p>solangfile::config_file(app='$app',fname='$fname')</p>\n"; 67 $lines = file($fname); 68 69 if ($app != 'setup') 70 { 71 $app = 'admin'; 72 } 73 foreach($lines as $n => $line) 74 { 75 while (ereg('\{lang_([^}]+)\}(.*)',$line,$found)) 76 { 77 $lang = str_replace('_',' ',$found[1]); 78 $this->plist[$lang] = $app; 79 80 $line = $found[2]; 81 } 82 } 83 } 84 85 function special_file($app,$fname,$langs_in) 86 { 87 //echo "<p>solangfile::special_file(app='$app',fname='$fname',langs_in='$langs_in')</p>\n"; 88 switch ($langs_in) 89 { 90 case 'config': 91 $this->config_file($app,$fname); 92 return; 93 case 'file_admin': 94 case 'file_preferences': 95 $app = substr($langs_in,5); 96 break; 97 case 'phpgwapi': 98 $app = 'common'; 99 break; 100 } 101 if (!function_exists('display_sidebox')) 102 { 103 function display_sidebox($appname,$menu_title,$file) // hook_sidebox_menu 104 { 105 unset($file['_NewLine_']); 106 $GLOBALS['file'] += $file; 107 } 108 function display_section($appname,$file,$file2='') // hook_preferences, hook_admin 109 { 110 if (is_array($file2)) 111 { 112 $file = $file2; 113 } 114 $GLOBALS['file'] += $file; 115 } 116 } 117 $GLOBALS['file'] = array(); 118 unset($GLOBALS['acl_manager']); 119 include($fname); 120 121 if (isset($GLOBALS['acl_manager'])) // hook_acl_manager 122 { 123 foreach($GLOBALS['acl_manager'] as $app => $data) 124 { 125 foreach ($data as $item => $arr) 126 { 127 foreach ($arr as $key => $val) 128 { 129 switch ($key) 130 { 131 case 'name': 132 $this->plist[$val] = $app; 133 break; 134 case 'rights': 135 foreach($val as $lang => $right) 136 { 137 $this->plist[$lang] = $app; 138 } 139 break; 140 } 141 } 142 } 143 } 144 } 145 if (count($GLOBALS['file'])) // hook_{admin|preferences|sidebox_menu} 146 { 147 foreach ($GLOBALS['file'] as $lang => $link) 148 { 149 $this->plist[$lang] = $app; 150 } 151 } 152 } 153 154 function parse_php_app($app,$fd) 155 { 156 $reg_expr = '('.implode('|',array_keys($this->functions)).")[ \t]*\([ \t]*(.*)$"; 157 define('SEP',filesystem_separator()); 158 $d=dir($fd); 159 while ($fn=$d->read()) 160 { 161 if (@is_dir($fd.$fn.SEP)) 162 { 163 if ( ($fn!='.')&&($fn!='..') && ($fn!='CVS') && ($fn!='.svn') ) 164 { 165 $this->parse_php_app($app,$fd.$fn.SEP); 166 } 167 } 168 elseif (is_readable($fd.$fn)) 169 { 170 if (isset($this->files[$fn])) 171 { 172 $this->special_file($app,$fd.$fn,$this->files[$fn]); 173 } 174 if (strpos($fn,'.php') === False) 175 { 176 continue; 177 } 178 $lines = file($fd.$fn); 179 180 foreach($lines as $n => $line) 181 { 182 //echo "line='$line', lines[1+$n]='".$lines[1+$n]."'<br>\n"; 183 while (eregi($reg_expr,$line,$parts)) 184 { 185 //echo "***func='$parts[1]', rest='$parts[2]'<br>\n"; 186 $args = $this->functions[$parts[1]]; 187 $rest = $parts[2]; 188 for($i = 1; $i <= $args[0]; ++$i) 189 { 190 $next = 1; 191 if (!$rest || strpos($rest,$del,1) === False) 192 { 193 $rest .= trim($lines[++$n]); 194 } 195 $del = $rest[0]; 196 if ($del == '"' || $del == "'") 197 { 198 //echo "rest='$rest'<br>\n"; 199 while (($next = strpos($rest,$del,$next)) !== False && $rest[$next-1] == '\\') 200 { 201 $rest = substr($rest,0,$next-1).substr($rest,$next); 202 } 203 if ($next === False) 204 { 205 break; 206 } 207 $phrase = str_replace('\\\\','\\',substr($rest,1,$next-1)); 208 //echo "next2=$next, phrase='$phrase'<br>\n"; 209 if ($args[0] == $i) 210 { 211 //if (!isset($this->plist[$phrase])) echo ">>>$phrase<<<<br>\n"; 212 $this->plist[$phrase] = $app; 213 array_shift($args); 214 if (!count($args)) 215 { 216 break; // no more args needed 217 } 218 } 219 $rest = substr($rest,$next+1); 220 } 221 if(!ereg("[ \t\n]*,[ \t\n]*(.*)$",$rest,$parts)) 222 { 223 break; // nothing found 224 } 225 $rest = $parts[1]; 226 } 227 $line = $rest; 228 } 229 } 230 } 231 } 232 $d->close(); 233 } 234 235 function missing_app($app,$userlang=en) 236 { 237 $cur_lang=$this->load_app($app,$userlang); 238 define('SEP',filesystem_separator()); 239 $fd = PHPGW_SERVER_ROOT . SEP . $app . SEP; 240 $this->plist = array(); 241 $this->parse_php_app($app == 'phpgwapi' ? 'common' : $app,$fd); 242 243 reset($this->plist); 244 return($this->plist); 245 } 246 247 /*! 248 @function add_app 249 @abstract loads all app phrases into langarray 250 @param $lang user lang variable (defaults to en) 251 */ 252 function add_app($app,$userlang='en') 253 { 254 define('SEP',filesystem_separator()); 255 256 $fd = PHPGW_SERVER_ROOT . SEP . $app . SEP . ($app == 'setup' ? 'lang' : 'setup'); 257 $fn = $fd . SEP . 'phpgw_' . $userlang . '.lang'; 258 if (@is_writeable($fn) || is_writeable($fd)) 259 { 260 $wr = True; 261 } 262 $this->src_apps = array($app => $app); 263 264 if (file_exists($fn)) 265 { 266 $this->src_file = $fn; 267 $fp = fopen($fn,'rb'); 268 while ($data = fgets($fp,8000)) 269 { 270 list($message_id,$app_name,$null,$content) = explode("\t",$data); 271 if(!$message_id) 272 { 273 continue; 274 } 275 //echo '<br>add_app(): adding phrase: $this->langarray["'.$message_id.'"]=' . trim($content); 276 $_mess_id = strtolower(trim($message_id)); 277 $app_name = trim($app_name); 278 $this->langarray[$_mess_id]['message_id'] = $_mess_id; 279 $this->langarray[$_mess_id]['app_name'] = $app_name; 280 $this->langarray[$_mess_id]['content'] = trim($content); 281 $this->src_apps[$app_name] = $app_name; 282 } 283 fclose($fp); 284 } 285 else 286 { 287 $this->src_file = lang('no file'); 288 } 289 // stuff class array listing apps that are included already 290 $this->loaded_apps[$userlang]['filename'] = $fn; 291 $this->loaded_apps[$userlang]['writeable'] = $wr; 292 293 if($this->debug) { _debug_array($this->langarray); } 294 @ksort($this->langarray); 295 return $this->langarray; 296 } 297 298 /*! 299 @function load_app 300 @abstract loads all app phrases into langarray 301 @param $lang user lang variable (defaults to en) 302 */ 303 function load_app($app,$userlang='en') 304 { 305 define('SEP',filesystem_separator()); 306 307 $langarray = array(); 308 $fd = PHPGW_SERVER_ROOT . SEP . $app . SEP . ($app == 'setup' ? 'lang' : 'setup'); 309 $fn = $fd . SEP . 'phpgw_' . $userlang . '.lang'; 310 if (@is_writeable($fn) || is_writeable($fd)) 311 { 312 $wr = True; 313 } 314 315 if (file_exists($fn)) 316 { 317 $this->tgt_file = $fn; 318 if ($fp = @fopen($fn,'rb')) 319 { 320 while ($data = fgets($fp,8000)) 321 { 322 list($message_id,$app_name,$null,$content) = explode("\t",$data); 323 if(!$message_id) 324 { 325 continue; 326 } 327 //echo '<br>add_app(): adding phrase: $this->langarray["'.$message_id.'"]=' . trim($content); 328 $_mess_id = strtolower(trim($message_id)); 329 $langarray[$_mess_id]['message_id'] = $_mess_id; 330 $langarray[$_mess_id]['app_name'] = trim($app_name); 331 $langarray[$_mess_id]['content'] = trim($content); 332 } 333 fclose($fp); 334 } 335 } 336 else 337 { 338 $this->tgt_file = lang('no file'); 339 } 340 // stuff class array listing apps that are included already 341 $this->loaded_apps[$userlang]['filename'] = $fn; 342 $this->loaded_apps[$userlang]['writeable'] = $wr; 343 if($this->debug) { _debug_array($langarray); } 344 @ksort($langarray); 345 return $langarray; 346 } 347 348 function list_langs() 349 { 350 $this->db->query("SELECT DISTINCT lang FROM phpgw_lang"); 351 while($this->db->next_record()) 352 { 353 $lang = $this->db->f('lang'); 354 $installed[] = $lang; 355 } 356 $installed = "('".implode("','",$installed)."')"; 357 358 // this shows first the installed, then the available and then the rest 359 $this->db->query("SELECT lang_id,lang_name,lang_id IN $installed as installed FROM phpgw_languages ORDER BY installed DESC,available DESC,lang_name"); 360 $i = 0; 361 while ($this->db->next_record()) 362 { 363 $languages[$i]['lang_id'] = $this->db->f('lang_id'); 364 $languages[$i]['lang_name'] = $this->db->f('lang_name'); 365 $i++; 366 } 367 @reset($languages); 368 if($this->debug) { _debug_array($languages); } 369 return $languages; 370 } 371 372 function write_file($app_name,$langarray,$userlang) 373 { 374 $fn = PHPGW_SERVER_ROOT . SEP . $app_name . SEP . ($app_name == 'setup' ? 'lang' : 'setup') . SEP . 'phpgw_' . $userlang . '.lang'; 375 if (file_exists($fn)) 376 { 377 $backup = $fn . '.old'; 378 @unlink($backup); 379 @rename($fn,$backup); 380 } 381 $fp = fopen($fn,'wb'); 382 while(list($mess_id,$data) = @each($langarray)) 383 { 384 fwrite($fp,$mess_id . "\t" . $data['app_name'] . "\t" . $userlang . "\t" . $data['content'] . "\n"); 385 } 386 fclose($fp); 387 return; 388 } 389 390 function loaddb($app_name,$userlang) 391 { 392 $langarray = $this->load_app($app_name,$userlang); 393 if (!is_array($langarray)) 394 { 395 return False; 396 } 397 398 $this->db->transaction_begin(); 399 400 $userlang = $this->db->db_addslashes($userlang); 401 foreach($langarray as $x => $data) 402 { 403 $message_id = $this->db->db_addslashes(trim(substr($data['message_id'],0,MAX_MESSAGE_ID_LENGTH))); 404 $app = $this->db->db_addslashes($data['app_name']); 405 $content = $this->db->db_addslashes($data['content']); 406 407 $addit = False; 408 /*echo '<br><br><pre> checking ' . $data['message_id'] . "\t" . $data['app_name'] . "\t" . $userlang . "\t" . $data['content'];*/ 409 $this->db->query("SELECT COUNT(*) FROM phpgw_lang" 410 ." WHERE message_id='$message_id' AND lang='$userlang' AND app_name='$app'",__LINE__,__FILE__); 411 $this->db->next_record(); 412 413 if ($this->db->f(0) == 0) 414 { 415 $addit = True; 416 /* echo '... no</pre>'; */ 417 } 418 else 419 { 420 /* echo '... yes</pre>'; */ 421 } 422 423 if ($addit) 424 { 425 if($data['message_id'] && $data['content']) 426 { 427 /* echo "<br>adding - insert into lang values ('" . $data['message_id'] . "','$app_name','$userlang','" . $data['content'] . "')"; */ 428 $this->db->query("INSERT into phpgw_lang VALUES ('$message_id','$app','$userlang','$content')",__LINE__,__FILE__); 429 } 430 } 431 else 432 { 433 if($data['message_id'] && $data['content']) 434 { 435 $this->db->query("UPDATE phpgw_lang SET content='$content'" 436 . " WHERE message_id='$message_id'" 437 . " AND app_name='$app' AND lang='$userlang'",__LINE__,__FILE__); 438 if ($this->db->affected_rows() > 0) 439 { 440/* 441 echo "<br>changing - update lang set content='". $data['content'] . "'" 442 . " where message_id='" . $data['message_id'] ."'" 443 . " and app_name='$app_name' and lang='$userlang'"; 444*/ 445 } 446 } 447 } 448 } 449 $this->db->transaction_commit(); 450 return lang('done'); 451 } 452 } 453?> 454