1<?php 2 3require_once dirname(__FILE__).'/accesscheck.php'; 4/* 5 6Languages, countries, and the charsets typically used for them 7http://www.w3.org/International/O-charset-lang.html 8 9*/ 10 11//# pick up languages from the lan directory 12$landir = dirname(__FILE__).'/locale/'; 13$d = opendir($landir); 14while ($lancode = readdir($d)) { 15 // print "<br/>".$lancode; 16 if (!in_array($landir, 17 array_keys($LANGUAGES)) && is_dir($landir.'/'.$lancode) && is_file($landir.'/'.$lancode.'/language_info') 18 ) { 19 $lan = @parse_ini_file($landir.'/'.$lancode.'/language_info'); 20 if (!isset($lan['gettext'])) { 21 $lan['gettext'] = $lancode; 22 } 23 if (!isset($lan['dir'])) { 24 $lan['dir'] = 'ltr'; 25 } 26 if (!empty($lan['name']) && !empty($lan['charset'])) { 27 $LANGUAGES[$lancode] = array($lan['name'], $lan['charset'], $lan['charset'], $lan['gettext'], $lan['dir']); 28 } 29 30// print '<br/>'.$landir.'/'.$lancode; 31 } 32} 33 34//# pick up other languages from DB 35if (Sql_table_exists('i18n')) { 36 $req = Sql_Query(sprintf('select lan,translation from %s where 37 original = "language-name" and lan not in ("%s")', $GLOBALS['tables']['i18n'], 38 implode('","', array_keys($LANGUAGES)))); 39 while ($row = Sql_Fetch_Assoc($req)) { 40 $LANGUAGES[$row['lan']] = array($row['translation'], 'UTF-8', 'UTF-8', $row['lan']); 41 } 42} 43 44function lanSort($a, $b) 45{ 46 return strcmp(strtolower($a[3]), strtolower($b[3])); 47} 48 49uasort($LANGUAGES, 'lanSort'); 50//print '<pre>'; 51//var_dump($LANGUAGES);exit; 52 53if (!empty($GLOBALS['SessionTableName'])) { 54 require_once dirname(__FILE__).'/sessionlib.php'; 55} 56@session_start(); 57 58if (isset($_POST['setlanguage']) && !empty($_POST['setlanguage']) && is_array($LANGUAGES[$_POST['setlanguage']])) { 59 //# just in case 60 $setlanguage = preg_replace('/[^\w_-]+/', '', $_POST['setlanguage']); 61 $_SESSION['adminlanguage'] = array( 62 'info' => $setlanguage, 63 'iso' => $setlanguage, 64 'charset' => $LANGUAGES[$setlanguage][1], 65 'dir' => $LANGUAGES[$setlanguage][4], 66 ); 67 SetCookie ( 'preferredLanguage', $setlanguage,time()+31536000); 68} elseif (empty($_SESSION['adminlanguage']) && isset($_COOKIE['preferredLanguage'])) { 69 $setlanguage = preg_replace('/[^\w_-]+/', '', $_COOKIE['preferredLanguage']); 70 $_SESSION['adminlanguage'] = array( 71 'info' => $setlanguage, 72 'iso' => $setlanguage, 73 'charset' => $LANGUAGES[$setlanguage][1], 74 'dir' => $LANGUAGES[$setlanguage][4], 75 ); 76} 77// var_dump($_SESSION['adminlanguage'] ); 78 79/* 80if (!empty($_SESSION['show_translation_colours'])) { 81 $GLOBALS['pageheader']['translationtools'] = ' 82 <script type="text/javascript" src="js/jquery.contextMenu.js"></script> 83 <link rel="stylesheet" href="js/jquery.contextMenu.css" /> 84 <ul id="translationMenu" class="contextMenu"> 85 <li class="translate"> 86 <a href="#translate">Translate</a> 87 </li> 88 <li class="quit separator"> 89 <a href="#quit">Quit</a> 90 </li> 91</ul> 92 <script type="text/javascript"> 93 $(document).ready(function(){ 94 $(".translate").contextMenu({ 95 menu: "translationMenu" 96 }, 97 function(action, el, pos) { 98 alert( 99 "Action: " + action + "\n\n" + 100 "Element ID: " + $(el).attr("id") + "\n\n" + 101 "X: " + pos.x + " Y: " + pos.y + " (relative to element)\n\n" + 102 "X: " + pos.docX + " Y: " + pos.docY+ " (relative to document)" 103 ); 104 }); 105 }); 106 </script> 107 108 '; 109} 110*/ 111 112if (!isset($_SESSION['adminlanguage']) || !is_array($_SESSION['adminlanguage'])) { 113 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { 114 $accept_lan = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); 115 } else { 116 $accept_lan = array($GLOBALS['default_system_language']); 117 } 118 $detectlan = ''; 119 120 /* @@@TODO 121 * we need a mapping from Accept-Language to gettext, see below 122 * 123 * eg nl-be becomes nl_BE 124 * 125 * currently "nl-be" will become "nl" and not "nl_BE"; 126 */ 127 128 foreach ($accept_lan as $lan) { 129 if (!$detectlan) { 130 if (preg_match('/^([\w-]+)/', $lan, $regs)) { 131 $code = $regs[1]; 132 if (isset($LANGUAGES[$code])) { 133 $detectlan = $code; 134 } elseif (strpos($code, '-') !== false) { 135 list($language, $country) = explode('-', $code); 136 if (isset($LANGUAGES[$language])) { 137 $detectlan = $language; 138 } 139 } 140 } 141 } 142 } 143 if (!$detectlan) { 144 $detectlan = $GLOBALS['default_system_language']; 145 } 146 147 $_SESSION['adminlanguage'] = array( 148 'info' => $detectlan, 149 'iso' => $detectlan, 150 'charset' => $LANGUAGES[$detectlan][1], 151 'dir' => $LANGUAGES[$detectlan][4], 152 ); 153} 154 155//# this interferes with the frontend if an admin is logged in. 156//# better split the frontend and backend charSets at some point 157//if (!isset($GLOBALS['strCharSet'])) { 158$GLOBALS['strCharSet'] = $_SESSION['adminlanguage']['charset']; 159 160//var_dump($_SESSION['adminlanguage']); 161//print '<h1>'. $GLOBALS['strCharSet'].'</h1>'; 162 163// internationalisation (I18N) 164 165class phplist_I18N 166{ 167 public $defaultlanguage = 'en'; 168 public $language = 'en'; 169 public $basedir = ''; 170 public $dir = 'ltr'; 171 private $hasGettext = false; 172 private $hasDB = false; 173 private $lan = array(); 174 175 public function __construct() 176 { 177 $this->basedir = dirname(__FILE__).'/locale/'; 178 $this->defaultlanguage = $GLOBALS['default_system_language']; 179 $this->language = $GLOBALS['default_system_language']; 180 181 if (isset($_SESSION['adminlanguage']) && isset($GLOBALS['LANGUAGES'][$_SESSION['adminlanguage']['iso']])) { 182 $this->language = $_SESSION['adminlanguage']['iso']; 183 $this->dir = $_SESSION['adminlanguage']['dir']; 184 } else { 185 unset($_SESSION['adminlanguage']); 186 $this->language = $GLOBALS['default_system_language']; 187 } 188 if (function_exists('gettext')) { 189 $this->hasGettext = true; 190 } 191 if (isset($_SESSION['hasI18Ntable'])) { 192 $this->hasDB = $_SESSION['hasI18Ntable']; 193 } elseif (Sql_Check_For_Table('i18n')) { 194 $_SESSION['hasI18Ntable'] = true; 195 $this->hasDB = true; 196 } else { 197 $_SESSION['hasI18Ntable'] = false; 198 } 199 200 if (isset($_GET['origpage']) && !empty($_GET['ajaxed'])) { //# used in ajaxed requests 201 $page = basename($_GET['origpage']); 202 } elseif (isset($_GET['page'])) { 203 $page = basename($_GET['page']); 204 } else { 205 $page = 'home'; 206 } 207 //# as we're including things, let's make sure it's clean 208 $page = preg_replace('/\W/', '', $page); 209 210 if (!empty($_GET['pi'])) { 211 $plugin_languagedir = $this->getPluginBasedir(); 212 if (is_dir($plugin_languagedir)) { 213 $this->basedir = $plugin_languagedir; 214 if (isset($GLOBALS['plugins'][$_GET['pi']])) { 215 $plugin = $GLOBALS['plugins'][$_GET['pi']]; 216 if ($plugin->enabled && $plugin->needI18N && $plugin->i18nLanguageDir()) { 217 $this->basedir = $plugin->i18nLanguageDir(); 218 } 219 } 220 } 221 } 222 223 $lan = array(); 224 225 if (is_file($this->basedir.$this->language.'/'.$page.'.php')) { 226 @include $this->basedir.$this->language.'/'.$page.'.php'; 227 } elseif (!isset($GLOBALS['developer_email'])) { 228 @include $this->basedir.$this->defaultlanguage.'/'.$page.'.php'; 229 } 230 $this->lan = $lan; 231 $lan = array(); 232 233 if (is_file($this->basedir.$this->language.'/common.php')) { 234 @include $this->basedir.$this->language.'/common.php'; 235 } elseif (!isset($GLOBALS['developer_email'])) { 236 @include $this->basedir.$this->defaultlanguage.'/common.php'; 237 } 238 $this->lan += $lan; 239 $lan = array(); 240 241 if (is_file($this->basedir.$this->language.'/frontend.php')) { 242 @include $this->basedir.$this->language.'/frontend.php'; 243 } elseif (!isset($GLOBALS['developer_email'])) { 244 @include $this->basedir.$this->defaultlanguage.'/frontend.php'; 245 } 246 $this->lan += $lan; 247 } 248 249 public function gettext($text) 250 { 251 bindtextdomain('phplist', './locale'); 252 textdomain('phplist'); 253 254 /* gettext is a bit messy, at least on my Ubuntu 10.10 machine 255 * 256 * if eg language is "nl" it won't find it. It'll need to be "nl_NL"; 257 * also the Ubuntu system needs to have the language installed, even if phpList has it 258 * it won't find it, if it's not on the system 259 * 260 * So, to e.g. get "nl" gettext support in phpList (on ubuntu, but presumably other linuxes), you'd have to do 261 * cd /usr/share/locales 262 * ./install-language-pack nl_NL 263 * dpkg-reconfigure locales 264 * 265 * but when you use "nl_NL", the language .mo can still be in "nl". 266 * However, it needs "nl/LC_MESSAGES/phplist.mo s, put a symlink LC_MESSAGES to itself 267 * 268 * the "utf-8" strangely enough needs to be added but can be spelled all kinds 269 * of ways, eg "UTF8", "utf-8" 270 * 271 * 272 * AND then of course the lovely Accept-Language vs gettext 273 * https://bugs.php.net/bug.php?id=25051 274 * 275 * Accept-Language is lowercase and with - and gettext is country uppercase and with underscore 276 * 277 * More ppl have come across that: http://grep.be/articles/php-accept 278 * 279 */ 280 281 //# so, to get the mapping from "nl" to "nl_NL", use a gettext map in the related directory 282 if (is_file(dirname(__FILE__).'/locale/'.$this->language.'/gettext_code')) { 283 $lan_map = file_get_contents(dirname(__FILE__).'/locale/'.$this->language.'/gettext_code'); 284 $lan_map = trim($lan_map); 285 } else { 286 //# try to do "fr_FR", or "de_DE", might work in most cases 287 //# hmm, not for eg fa_IR or zh_CN so they'll need the above file 288 // http://www.gnu.org/software/gettext/manual/gettext.html#Language-Codes 289 $lan_map = $this->language.'_'.strtoupper($this->language); 290 } 291 292 putenv('LANGUAGE='.$lan_map.'.utf-8'); 293 setlocale(LC_ALL, $lan_map.'.utf-8'); 294 bind_textdomain_codeset('phplist', 'UTF-8'); 295 $gt = gettext($text); 296 if ($gt && $gt != $text) { 297 return $gt; 298 } 299 } 300 301 public function getCachedTranslation($text) 302 { 303 if (!isset($_SESSION['translations']) || !is_array($_SESSION['translations'])) { 304 return false; 305 } 306 if (isset($_SESSION['translations'][$text])) { 307 $age = time() - $_SESSION['translations'][$text]['ts']; 308 if ($age < 3600) { //# timeout after a while 309 return $_SESSION['translations'][$text]['trans']; 310 } else { 311 unset($_SESSION['translations'][$text]); 312 } 313 } 314 } 315 316 public function setCachedTranslation($text, $translation) 317 { 318 if (!isset($_SESSION['translations']) || !is_array($_SESSION['translations'])) { 319 $_SESSION['translations'] = array(); 320 } 321 // mark it as translated even if not, to avoid fetching it every time 322 if (empty($translation)) { 323 $translation = $text; 324 } 325 $_SESSION['translations'][$text] = array( 326 'trans' => $translation, 327 'ts' => time(), 328 ); 329 } 330 331 public function resetCache() 332 { 333 unset($_SESSION['translations']); 334 } 335 336 public function databaseTranslation($text) 337 { 338 if (!$this->hasDB) { 339 return ''; 340 } 341 if (empty($GLOBALS['database_connection'])) { 342 return ''; 343 } 344 if ($cache = $this->getCachedTranslation($text)) { 345 return $cache; 346 } 347 348 $tr = Sql_Fetch_Row_Query(sprintf('select translation from '.$GLOBALS['tables']['i18n'].' where original = "%s" and lan = "%s"', 349 sql_escape(trim($text)), $this->language), 1); 350 if (empty($tr[0])) { 351 $tr = Sql_Fetch_Row_Query(sprintf('select translation from '.$GLOBALS['tables']['i18n'].' where original = "%s" and lan = "%s"', 352 sql_escape($text), $this->language), 1); 353 } 354 if (empty($tr[0])) { 355 $tr = Sql_Fetch_Row_Query(sprintf('select translation from '.$GLOBALS['tables']['i18n'].' where original = "%s" and lan = "%s"', 356 sql_escape(str_replace('"', '\"', $text)), $this->language), 1); 357 } 358 $translated = !empty($tr[0]) ? stripslashes($tr[0]) : ''; 359 $this->setCachedTranslation($text, $translated); 360 361 return $translated; 362 } 363 364 public function pageTitle($page) 365 { 366 //# try gettext and otherwise continue 367 if ($this->hasGettext) { 368 $gettext = $this->gettext($page); 369 if (!empty($gettext)) { 370 return $gettext; 371 } 372 } 373 $page_title = ''; 374 $dbTitle = $this->databaseTranslation('pagetitle:'.$page); 375 if ($dbTitle) { 376 //# quite a few translators keep the pagetitle: in the translation 377 $dbTitle = str_ireplace('pagetitle:', '', $dbTitle); 378 $page_title = $dbTitle; 379 } elseif (is_file(dirname(__FILE__).'/locale/'.$this->language.'/pagetitles.php')) { 380 include dirname(__FILE__).'/locale/'.$this->language.'/pagetitles.php'; 381 } elseif (is_file(dirname(__FILE__).'/lan/'.$this->language.'/pagetitles.php')) { 382 include dirname(__FILE__).'/lan/'.$this->language.'/pagetitles.php'; 383 } 384 if (preg_match('/pi=([\w]+)/', $page, $regs)) { 385 //# @@TODO call plugin to ask for title 386 if (isset($GLOBALS['plugins'][$regs[1]])) { 387 $title = $GLOBALS['plugins'][$regs[1]]->pageTitle($page); 388 } else { 389 $title = $regs[1].' - '.$page; 390 } 391 } elseif (!empty($page_title)) { 392 $title = $page_title; 393 } else { 394 $title = ucfirst($page); 395 } 396 397 return $title; 398 } 399 400 public function pageTitleHover($page) 401 { 402 $hoverText = ''; 403 $dbTitle = $this->databaseTranslation('pagetitlehover:'.$page); 404 if ($dbTitle) { 405 $dbTitle = str_ireplace('pagetitlehover:', '', $dbTitle); 406 $hoverText = $dbTitle; 407 } else { 408 $hoverText = $this->pageTitle($page); 409 //# is this returns itself, wipe it, so the linktext is used instead 410 if ($hoverText == $page) { 411 $hoverText = ''; 412 } 413 } 414 if (!empty($hoverText)) { 415 return $hoverText; 416 } 417 418 return ''; 419 } 420 421 public function formatText($text) 422 { 423 // we've decided to spell phplist with uc L 424 $text = str_ireplace('phplist', 'phpList', $text); 425 426 if (isset($GLOBALS['developer_email'])) { 427 if (!empty($_SESSION['show_translation_colours'])) { 428 return '<span style="color:#A704FF">'.str_replace("\n", '', $text).'</span>'; 429 } 430// return 'TE'.$text.'XT'; 431 } 432// return '<span class="translateabletext">'.str_replace("\n","",$text).'</span>'; 433 return str_replace("\n", '', $text); 434 } 435 436 /** 437 * obsolete. 438 */ 439 public function missingText($text) 440 { 441 if (isset($GLOBALS['developer_email'])) { 442 if (isset($_GET['page'])) { 443 $page = $_GET['page']; 444 } else { 445 $page = 'home'; 446 } 447 $pl = $prefix = ''; 448 if (!empty($_GET['pi'])) { 449 $pl = $_GET['pi']; 450 $pl = preg_replace('/\W/', '', $pl); 451 $prefix = $pl.'_'; 452 } 453 454 $msg = ' 455 456 Undefined text reference in page ' .$page.' 457 458 ' .$text; 459 460 $page = preg_replace('/\W/', '', $page); 461 462 //sendMail($GLOBALS["developer_email"],"phplist dev, missing text",$msg); 463 $line = "'".str_replace("'", "\'", $text)."' => '".str_replace("'", "\'", $text)."',"; 464// if (is_file($this->basedir.'/en/'.$page.'.php') && $_SESSION['adminlanguage']['iso'] == 'en') { 465 if (empty($prefix) && $_SESSION['adminlanguage']['iso'] == 'en') { 466 $this->appendText($this->basedir.'/en/'.$page.'.php', $line); 467 } else { 468 $this->appendText('/tmp/'.$prefix.$page.'.php', $line); 469 } 470 471 if (!empty($_SESSION['show_translation_colours'])) { 472 return '<span style="color: #FF1717">'.$text.'</span>'; //MISSING TEXT 473 } 474 } 475 476 return $text; 477 } 478 479 public function appendText($file, $text) 480 { 481 return; 482 $filecontents = ''; 483 if (is_file($file)) { 484 $filecontents = file_get_contents($file); 485 } else { 486 $filecontents = '<?php 487 488$lan = array( 489 490); 491 492 ?>'; 493 } 494 495// print "<br/>Writing $text to $file"; 496 $filecontents = preg_replace("/\n/", '@@NL@@', $filecontents); 497 $filecontents = str_replace(');', ' '.$text."\n);", $filecontents); 498 $filecontents = str_replace('@@NL@@', "\n", $filecontents); 499 500 $dir = dirname($file); 501 if (!is_writable($dir) || (is_file($file) && !is_writable($file))) { 502 $newfile = basename($file); 503 $file = '/tmp/'.$newfile; 504 } 505 506 file_put_contents($file, $filecontents); 507 } 508 509 public function getPluginBasedir() 510 { 511 $pl = $_GET['pi']; 512 $pl = preg_replace('/\W/', '', $pl); 513 $pluginroot = ''; 514 if (isset($GLOBALS['plugins'][$pl]) && is_object($GLOBALS['plugins'][$pl])) { 515 $pluginroot = $GLOBALS['plugins'][$pl]->coderoot; 516 } 517 if (is_dir($pluginroot.'/lan/')) { 518 return $pluginroot.'/lan/'; 519 } else { 520 return $pluginroot.'/'; 521 } 522 } 523 524 public function initFSTranslations($language = '') 525 { 526 if (empty($language)) { 527 $language = $this->language; 528 } 529 $translations = parsePO(file_get_contents(dirname(__FILE__).'/locale/'.$language.'/phplist.po')); 530 $time = filemtime(dirname(__FILE__).'/locale/'.$language.'/phplist.po'); 531 $this->updateDBtranslations($translations, $time, $language); 532 } 533 534 public function updateDBtranslations($translations, $time, $language = '') 535 { 536 if (empty($language)) { 537 $language = $this->language; 538 } 539 if (count($translations)) { 540 foreach ($translations as $orig => $trans) { 541 Sql_Query('replace into '.$GLOBALS['tables']['i18n'].' (lan,original,translation) values("'.$language.'","'.sql_escape($orig).'","'.sql_escape($trans).'")'); 542 } 543 } 544 $this->resetCache(); 545 saveConfig('lastlanguageupdate-'.$language, $time, 0); 546 } 547 548 public function getTranslation($text, $page, $basedir) 549 { 550 551 //# try DB, as it will be the latest 552 if ($this->hasDB) { 553 $db_trans = $this->databaseTranslation($text); 554 if (!empty($db_trans)) { 555 return $this->formatText($db_trans); 556 } elseif (is_file(dirname(__FILE__).'/locale/'.$this->language.'/phplist.po')) { 557 if (function_exists('getConfig')) { 558 $lastUpdate = getConfig('lastlanguageupdate-'.$this->language); 559 $thisUpdate = filemtime(dirname(__FILE__).'/locale/'.$this->language.'/phplist.po'); 560 if (LANGUAGE_AUTO_UPDATE && $thisUpdate > $lastUpdate && !empty($_SESSION['adminloggedin'])) { 561 //# we can't translate this, as it'll be recursive 562 $GLOBALS['pagefooter']['transupdate'] = '<script type="text/javascript">initialiseTranslation("Initialising phpList in your language, please wait.");</script>'; 563 } 564 } 565 //$this->updateDBtranslations($translations,$time); 566 } 567 } 568 569 //# next try gettext, although before that works, it requires loads of setting up 570 //# but who knows 571 if ($this->hasGettext) { 572 $gettext = $this->gettext($text); 573 if (!empty($gettext)) { 574 return $this->formatText($gettext); 575 } 576 } 577 578 $lan = $this->lan; 579 580 if (trim($text) == '') { 581 return ''; 582 } 583 if (strip_tags($text) == '') { 584 return $text; 585 } 586 if (isset($lan[$text])) { 587 return $this->formatText($lan[$text]); 588 } 589 if (isset($lan[strtolower($text)])) { 590 return $this->formatText($lan[strtolower($text)]); 591 } 592 if (isset($lan[strtoupper($text)])) { 593 return $this->formatText($lan[strtoupper($text)]); 594 } 595 596 return ''; 597 } 598 599 public function get($text) 600 { 601 if (trim($text) == '') { 602 return ''; 603 } 604 if (strip_tags($text) == '') { 605 return $text; 606 } 607 $translation = ''; 608 609 $this->basedir = dirname(__FILE__).'/lan/'; 610 if (isset($_GET['origpage']) && !empty($_GET['ajaxed'])) { //# used in ajaxed requests 611 $page = basename($_GET['origpage']); 612 } elseif (isset($_GET['page'])) { 613 $page = basename($_GET['page']); 614 } else { 615 $page = 'home'; 616 } 617 $page = preg_replace('/\W/', '', $page); 618 619 if (!empty($_GET['pi'])) { 620 $plugin_languagedir = $this->getPluginBasedir(); 621 if (is_dir($plugin_languagedir)) { 622 $translation = $this->getTranslation($text, $page, $plugin_languagedir); 623 } 624 } 625 626 //# if a plugin did not return the translation, find it in core 627 if (empty($translation)) { 628 $translation = $this->getTranslation($text, $page, $this->basedir); 629 } 630 631 // print $this->language.' '.$text.' '.$translation. '<br/>'; 632 633 // spelling mistake, retry with old spelling 634 if ($text == 'over threshold, user marked unconfirmed' && empty($translation)) { 635 return $this->get('over treshold, user marked unconfirmed'); 636 } 637 638 if (!empty($translation)) { 639 return $translation; 640 } else { 641 return $this->missingText($text); 642 } 643 } 644} 645 646function getTranslationUpdates() 647{ 648 //# @@@TODO add some more error handling 649 $LU = false; 650 $lan_update = fetchUrl(TRANSLATIONS_XML); 651 if (!empty($lan_update)) { 652 $LU = @simplexml_load_string($lan_update); 653 } 654 655 return $LU; 656} 657 658$I18N = new phplist_I18N(); 659if (!empty($setlanguage)) { 660 $I18N->resetCache(); 661} 662/* add a shortcut that seems common in other apps 663 * function s($text) 664 * @param $text string the text to find 665 * @params 2-n variable - parameters to pass on to the sprintf of the text 666 * @return translated text with parameters filled in 667 * 668 * 669 * eg s("This is a %s with a %d and a %0.2f","text",6,1.98765); 670 * 671 * will look for the translation of the string and substitute the parameters 672 * 673 **/ 674 675function s($text) 676{ 677 //# allow overloading with sprintf paramaters 678 $translation = $GLOBALS['I18N']->get($text); 679 680 if (func_num_args() > 1) { 681 $args = func_get_args(); 682 array_shift($args); 683 $translation = vsprintf($translation, $args); 684 } 685 686 return $translation; 687} 688 689/** 690 * function snbr 691 * similar to function s, but without overloading params 692 * will return the translated text with spaces turned to so that they won't wrap 693 * mostly useful for buttons. 694 */ 695function snbr($text) 696{ 697 $trans = s($text); 698 $trans = str_replace(' ', ' ', $trans); 699 700 return $trans; 701} 702 703/** 704 * function sJS 705 * get the translation from the S function, but escape single quotes for use in Javascript. 706 */ 707function sjs($text) 708{ 709 $trans = s($text); 710 $trans = str_replace("'", "\'", $trans); 711 712 return $trans; 713} 714 715/** 716 * function sHtmlEntities 717 * get the translation from the s function, but escape it by using htmlentities. 718 */ 719function sHtmlEntities ($text) { 720 return htmlentities(s($text)); 721} 722 723function parsePo($translationUpdate) 724{ 725 $translation_lines = explode("\n", $translationUpdate); 726 $original = ''; 727 $flagOrig = $flagTrans = false; 728 $translation = ''; 729 $translations = array(); 730 foreach ($translation_lines as $line) { 731 if (preg_match('/^msgid "(.*)"/', $line, $regs)) { 732 $original = $regs[1]; 733 $flagOrig = true; 734 } elseif (preg_match('/^msgstr "(.*)"/', $line, $regs)) { 735 $flagOrig = false; 736 $flagTrans = true; 737 $translation = $regs[1]; 738 } elseif (preg_match('/^"(.*)"/', $line, $regs) && !(preg_match('/^#/', $line) || preg_match('/^\s+$/', 739 $line) || $line == '') 740 ) { 741 //# wrapped to multiple lines, can be both original and translation 742 if ($flagTrans) { 743 $translation .= $regs[1]; 744 } else { 745 $original .= $regs[1]; 746 } 747 } elseif (preg_match('/^#/', $line) || preg_match('/^\s+$/', $line) || $line == '') { 748 $original = $translation = ''; 749 $flagOrig = $flagTrans = false; 750 } 751 if (!empty($original) && !empty($translation)) { 752 $translations[trim($original)] = trim($translation); 753 } 754 } 755 756 return $translations; 757} 758