1af1904f9SAndreas Gohr<?php 2af1904f9SAndreas Gohr/** 3af1904f9SAndreas Gohr * Translation Plugin: Simple multilanguage plugin 4af1904f9SAndreas Gohr * 5af1904f9SAndreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6af1904f9SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 7af1904f9SAndreas Gohr */ 8af1904f9SAndreas Gohr 9af1904f9SAndreas Gohr// must be run within Dokuwiki 10af1904f9SAndreas Gohrif(!defined('DOKU_INC')) die(); 11af1904f9SAndreas Gohr 12af1904f9SAndreas Gohrclass helper_plugin_translation extends DokuWiki_Plugin { 13af1904f9SAndreas Gohr var $trans = array(); 14af1904f9SAndreas Gohr var $tns = ''; 157c54a0a6SAndreas Gohr var $defaultlang = ''; 1649a71a89SAndreas Gohr var $LN = array(); // hold native names 17af1904f9SAndreas Gohr 18af1904f9SAndreas Gohr /** 19af1904f9SAndreas Gohr * Initialize 20af1904f9SAndreas Gohr */ 21af1904f9SAndreas Gohr function helper_plugin_translation(){ 227c54a0a6SAndreas Gohr global $conf; 23af1904f9SAndreas Gohr require_once(DOKU_INC.'inc/pageutils.php'); 24af1904f9SAndreas Gohr require_once(DOKU_INC.'inc/utf8.php'); 25af1904f9SAndreas Gohr 26af1904f9SAndreas Gohr // load wanted translation into array 27af1904f9SAndreas Gohr $this->trans = strtolower(str_replace(',',' ',$this->getConf('translations'))); 28af1904f9SAndreas Gohr $this->trans = array_unique(array_filter(explode(' ',$this->trans))); 29af1904f9SAndreas Gohr sort($this->trans); 307c54a0a6SAndreas Gohr 3149a71a89SAndreas Gohr // load language names 3249a71a89SAndreas Gohr $this->LN = confToHash(dirname(__FILE__).'/lang/langnames.txt'); 3349a71a89SAndreas Gohr 347c54a0a6SAndreas Gohr // get default translation 357c54a0a6SAndreas Gohr if(!$conf['lang_before_translation']){ 367c54a0a6SAndreas Gohr $dfl = $conf['lang']; 377c54a0a6SAndreas Gohr } else { 387c54a0a6SAndreas Gohr $dfl = $conf['lang_before_translation']; 397c54a0a6SAndreas Gohr } 407c54a0a6SAndreas Gohr if(in_array($dfl,$this->trans)){ 417c54a0a6SAndreas Gohr $this->defaultlang = $dfl; 427c54a0a6SAndreas Gohr }else{ 437c54a0a6SAndreas Gohr $this->defaultlang = ''; 44af1904f9SAndreas Gohr array_unshift($this->trans,''); 457c54a0a6SAndreas Gohr } 467c54a0a6SAndreas Gohr 47af1904f9SAndreas Gohr 48af1904f9SAndreas Gohr $this->tns = cleanID($this->getConf('translationns')); 49af1904f9SAndreas Gohr if($this->tns) $this->tns .= ':'; 50af1904f9SAndreas Gohr } 51af1904f9SAndreas Gohr 52af1904f9SAndreas Gohr /** 53af1904f9SAndreas Gohr * Check if the given ID is a translation and return the language code. 54af1904f9SAndreas Gohr */ 55af1904f9SAndreas Gohr function getLangPart($id){ 56*26522e09SAndreas Gohr list($lng) = $this->getTransParts($id); 57*26522e09SAndreas Gohr return $lng; 58af1904f9SAndreas Gohr } 59*26522e09SAndreas Gohr 60*26522e09SAndreas Gohr /** 61*26522e09SAndreas Gohr * Check if the given ID is a translation and return the language code and 62*26522e09SAndreas Gohr * the id part. 63*26522e09SAndreas Gohr */ 64*26522e09SAndreas Gohr function getTransParts($id){ 65*26522e09SAndreas Gohr $rx = '/^'.$this->tns.'('.join('|',$this->trans).'):(.*)/'; 66*26522e09SAndreas Gohr if(preg_match($rx,$id,$match)){ 67*26522e09SAndreas Gohr return array($match[1],$match[2]); 68*26522e09SAndreas Gohr } 69*26522e09SAndreas Gohr return array('',$id); 70af1904f9SAndreas Gohr } 71af1904f9SAndreas Gohr 72af1904f9SAndreas Gohr /** 737053cd66SAndreas Gohr * Returns the browser language if it matches with one of the configured 747053cd66SAndreas Gohr * languages 757053cd66SAndreas Gohr */ 767053cd66SAndreas Gohr function getBrowserLang(){ 777053cd66SAndreas Gohr $rx = '/(^|,|:|;|-)('.join('|',$this->trans).')($|,|:|;|-)/i'; 787053cd66SAndreas Gohr if(preg_match($rx,$_SERVER['HTTP_ACCEPT_LANGUAGE'],$match)){ 797053cd66SAndreas Gohr return strtolower($match[2]); 807053cd66SAndreas Gohr } 817053cd66SAndreas Gohr return false; 827053cd66SAndreas Gohr } 837053cd66SAndreas Gohr 847053cd66SAndreas Gohr 857053cd66SAndreas Gohr /** 867c54a0a6SAndreas Gohr * Returns the ID and name to the wanted translation, empty 877c54a0a6SAndreas Gohr * $lng is default lang 88af1904f9SAndreas Gohr */ 89af1904f9SAndreas Gohr function buildTransID($lng,$idpart){ 90af1904f9SAndreas Gohr global $conf; 91af1904f9SAndreas Gohr global $saved_conf; 92af1904f9SAndreas Gohr if($lng){ 93af1904f9SAndreas Gohr $link = ':'.$this->tns.$lng.':'.$idpart; 94af1904f9SAndreas Gohr $name = $lng; 95af1904f9SAndreas Gohr }else{ 96af1904f9SAndreas Gohr $link = ':'.$this->tns.$idpart; 97af1904f9SAndreas Gohr if(!$conf['lang_before_translation']){ 98af1904f9SAndreas Gohr $name = $conf['lang']; 99af1904f9SAndreas Gohr } else { 100af1904f9SAndreas Gohr $name = $conf['lang_before_translation']; 101af1904f9SAndreas Gohr } 102af1904f9SAndreas Gohr } 103af1904f9SAndreas Gohr return array($link,$name); 104af1904f9SAndreas Gohr } 105af1904f9SAndreas Gohr 1061469199dSAndreas Gohr /** 10784877e9bSAndreas Gohr * Check if current ID should be translated and any GUI 10884877e9bSAndreas Gohr * should be shown 10984877e9bSAndreas Gohr */ 11084877e9bSAndreas Gohr function istranslatable($id,$checkact=true){ 11184877e9bSAndreas Gohr global $ACT; 11284877e9bSAndreas Gohr 11384877e9bSAndreas Gohr if($checkact && $ACT != 'show') return false; 11484877e9bSAndreas Gohr if($this->tns && strpos($id,$this->tns) !== 0) return false; 11584877e9bSAndreas Gohr $skiptrans = trim($this->getConf('skiptrans')); 11684877e9bSAndreas Gohr if($skiptrans && preg_match('/'.$skiptrans.'/ui',':'.$id)) return false; 11784877e9bSAndreas Gohr $meta = p_get_metadata($id); 11884877e9bSAndreas Gohr if($meta['plugin']['translation']['notrans']) return false; 11984877e9bSAndreas Gohr 12084877e9bSAndreas Gohr return true; 12184877e9bSAndreas Gohr } 12284877e9bSAndreas Gohr 12301dd7da9SAndreas Gohr /** 12401dd7da9SAndreas Gohr * Return the (localized) about link 12501dd7da9SAndreas Gohr * 12601dd7da9SAndreas Gohr * @fixme why is this doing the detection stuff again? 12701dd7da9SAndreas Gohr */ 12801dd7da9SAndreas Gohr function showAbout() { 129c9640767STomasz Tomasik global $ID; 130c9640767STomasz Tomasik global $conf; 131c9640767STomasz Tomasik global $INFO; 132c9640767STomasz Tomasik 133c9640767STomasz Tomasik $this->checkage(); 134c9640767STomasz Tomasik 135c9640767STomasz Tomasik $LN = confToHash(dirname(__FILE__).'/lang/langnames.txt'); 136c9640767STomasz Tomasik 137c9640767STomasz Tomasik $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/'; 138c9640767STomasz Tomasik $idpart = preg_replace($rx,'',$ID); 139c9640767STomasz Tomasik 140c9640767STomasz Tomasik $out = ''; 141c9640767STomasz Tomasik $out .= '<sup>'; 142c9640767STomasz Tomasik if($this->getConf('localabout')){ 143c9640767STomasz Tomasik $lc = ''; 144c9640767STomasz Tomasik 145c9640767STomasz Tomasik //try main lang namespace 146c9640767STomasz Tomasik foreach($this->trans as $t){ 147c9640767STomasz Tomasik list($link,$name) = $this->buildTransID($t,$idpart); 148c9640767STomasz Tomasik $link = cleanID($link); 149c9640767STomasz Tomasik if($ID == $link){ 150c9640767STomasz Tomasik $lc = hsc($name); 151c9640767STomasz Tomasik } 152c9640767STomasz Tomasik if ($lc) break; 153c9640767STomasz Tomasik } 154c9640767STomasz Tomasik 155c9640767STomasz Tomasik //try browser language 156c9640767STomasz Tomasik if(!$lc) $lc = $this->getBrowserLang(); 157c9640767STomasz Tomasik 158c9640767STomasz Tomasik //try wiki language 159c9640767STomasz Tomasik if(!$lc) $lc = $conf['lang']; 160c9640767STomasz Tomasik 161c9640767STomasz Tomasik if(!$lc) { //can't find language 162c9640767STomasz Tomasik $localabout = $this->getConf('about'); //http://localhost/dokuwiki/doku.php?id=translation:about 163c9640767STomasz Tomasik } else { //i found language! 164c9640767STomasz Tomasik $localabout = $lc.':'.$this->getConf('about'); //http://localhost/dokuwiki/doku.php?id=en:translation:about 165c9640767STomasz Tomasik } 166c9640767STomasz Tomasik 167c9640767STomasz Tomasik //make link 168c9640767STomasz Tomasik $out .= html_wikilink($localabout,'?'); 16901dd7da9SAndreas Gohr } else { 170c9640767STomasz Tomasik $out .= html_wikilink($this->getConf('about'),'?'); 171c9640767STomasz Tomasik } 172c9640767STomasz Tomasik $out .= '</sup>'; 173c9640767STomasz Tomasik 174c9640767STomasz Tomasik return $out; 175c9640767STomasz Tomasik } 176c9640767STomasz Tomasik 17784877e9bSAndreas Gohr /** 1781469199dSAndreas Gohr * Displays the available and configured translations. Needs to be placed in the template. 1791469199dSAndreas Gohr */ 1801469199dSAndreas Gohr function showTranslations(){ 1811469199dSAndreas Gohr global $ID; 1821469199dSAndreas Gohr global $conf; 1831469199dSAndreas Gohr global $INFO; 1841469199dSAndreas Gohr 18584877e9bSAndreas Gohr if(!$this->istranslatable($ID)) return; 18684877e9bSAndreas Gohr 18784877e9bSAndreas Gohr $this->checkage(); 1881469199dSAndreas Gohr 18939ecab8bSAndreas Gohr $LN = confToHash(dirname(__FILE__).'/lang/langnames.txt'); 19039ecab8bSAndreas Gohr 1911469199dSAndreas Gohr $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/'; 1921469199dSAndreas Gohr $idpart = preg_replace($rx,'',$ID); 1931469199dSAndreas Gohr 1941469199dSAndreas Gohr $out = '<div class="plugin_translation">'; 195c9640767STomasz Tomasik 196c9640767STomasz Tomasik //show text 197c9640767STomasz Tomasik if ($this->getConf('description')){ 1981469199dSAndreas Gohr $out .= '<span>'.$this->getLang('translations'); 199c9640767STomasz Tomasik if ($this->getConf('showabout')) $out .= $this->showAbout(); 2001469199dSAndreas Gohr $out .= ':</span> '; 201c9640767STomasz Tomasik } 2021469199dSAndreas Gohr 20301dd7da9SAndreas Gohr if($this->getConf('dropdown')){ // use dropdown fixme move to own functions 2041469199dSAndreas Gohr if($INFO['exists']){ 2051469199dSAndreas Gohr $class = 'wikilink1'; 2061469199dSAndreas Gohr }else{ 2071469199dSAndreas Gohr $class = 'wikilink2'; 2081469199dSAndreas Gohr } 209c9640767STomasz Tomasik 21001dd7da9SAndreas Gohr $out2 = ""; //FIXME ugly name 2111469199dSAndreas Gohr foreach($this->trans as $t){ 2121469199dSAndreas Gohr list($link,$name) = $this->buildTransID($t,$idpart); 2131469199dSAndreas Gohr $link = cleanID($link); 2141469199dSAndreas Gohr if($ID == $link){ 2151469199dSAndreas Gohr $sel = ' selected="selected"'; 21601dd7da9SAndreas Gohr if($this->getConf('dropdown2')) { //FIXME ugly name 217c9640767STomasz Tomasik $out .= $this->makecountrylink($LN, $idpart, $t, false); 218c9640767STomasz Tomasik $out .= " "; 219c9640767STomasz Tomasik } 2201469199dSAndreas Gohr }else{ 2211469199dSAndreas Gohr $sel = ''; 2221469199dSAndreas Gohr } 2231469199dSAndreas Gohr if(page_exists($link,'',false)){ 2241469199dSAndreas Gohr $class = 'wikilink1'; 2251469199dSAndreas Gohr }else{ 2261469199dSAndreas Gohr $class = 'wikilink2'; 2271469199dSAndreas Gohr } 228c9640767STomasz Tomasik 229c9640767STomasz Tomasik //linktitle 230c9640767STomasz Tomasik $linktitle = ''; 231c9640767STomasz Tomasik if (strlen($LN[$name]) > 0){ 232c9640767STomasz Tomasik $linktitle = $LN[$name]; 233c9640767STomasz Tomasik } else{ 234c9640767STomasz Tomasik $linktitle = hsc($name); 2351469199dSAndreas Gohr } 236c9640767STomasz Tomasik 237c9640767STomasz Tomasik $out2 .= '<option value="'.$link.'"'.$sel.' class="'.$class.'" title="'.$linktitle.'">'.hsc($name).'</option>'; 238c9640767STomasz Tomasik } 239c9640767STomasz Tomasik $out .= '<form action="'.wl().'" id="translation__dropdown">'; 240c9640767STomasz Tomasik $out .= '<select name="id" class="'.$class.'">'; 241c9640767STomasz Tomasik $out .= $out2; 2421469199dSAndreas Gohr $out .= '</select>'; 2431469199dSAndreas Gohr $out .= '<input name="go" type="submit" value="→" />'; 2441469199dSAndreas Gohr $out .= '</form>'; 245c9640767STomasz Tomasik 246c9640767STomasz Tomasik //link to about (right) 247c9640767STomasz Tomasik if (!$this->getConf('description') && $this->getConf('showabout')) { 248c9640767STomasz Tomasik $out .= ' '; 249c9640767STomasz Tomasik $out .= $this->showAbout(); 25039ecab8bSAndreas Gohr } 251c9640767STomasz Tomasik }else{ // use list 252c9640767STomasz Tomasik $out .= '<ul>'; 253c9640767STomasz Tomasik 25401dd7da9SAndreas Gohr // FIXME what's this? 255c9640767STomasz Tomasik if (!$this->getConf('description') && $this->getConf('showabout')) { 256c9640767STomasz Tomasik $out .= ' '; 257c9640767STomasz Tomasik $out .= $this->showAbout(); 258c9640767STomasz Tomasik } 259c9640767STomasz Tomasik 260c9640767STomasz Tomasik foreach($this->trans as $t){ 261c9640767STomasz Tomasik $out .= $this->makecountrylink($LN, $idpart, $t, true); 2621469199dSAndreas Gohr } 2631469199dSAndreas Gohr $out .= '</ul>'; 2641469199dSAndreas Gohr } 2651469199dSAndreas Gohr 2661469199dSAndreas Gohr $out .= '</div>'; 2671469199dSAndreas Gohr 2681469199dSAndreas Gohr return $out; 2691469199dSAndreas Gohr } 270af1904f9SAndreas Gohr 27101dd7da9SAndreas Gohr /** 27201dd7da9SAndreas Gohr * Create the link or option for a single translation 27301dd7da9SAndreas Gohr * 27401dd7da9SAndreas Gohr * @fixme bad name - translations are not about countries 27501dd7da9SAndreas Gohr * @param $LN string The language 27601dd7da9SAndreas Gohr * @param $idpart string The ID of the translated page 27701dd7da9SAndreas Gohr * @param $t FIXME 27801dd7da9SAndreas Gohr * @param $div bool true for lists, false for dropdown FIXME 27901dd7da9SAndreas Gohr * @returns FIXME 28001dd7da9SAndreas Gohr */ 28101dd7da9SAndreas Gohr function makecountrylink($LN, $idpart, $t, $div) { 282c9640767STomasz Tomasik global $ID; 283c9640767STomasz Tomasik global $conf; 284c9640767STomasz Tomasik global $INFO; 285c9640767STomasz Tomasik 286c9640767STomasz Tomasik require(DOKU_PLUGIN.'translation/flags/langnames.php'); 287c9640767STomasz Tomasik 288c9640767STomasz Tomasik list($link,$name) = $this->buildTransID($t,$idpart); 289c9640767STomasz Tomasik $link = cleanID($link); 290c9640767STomasz Tomasik if(page_exists($link,'',false)){ 291c9640767STomasz Tomasik $class = 'wikilink1'; 292c9640767STomasz Tomasik }else{ 293c9640767STomasz Tomasik $class = 'wikilink2'; 294c9640767STomasz Tomasik } 295c9640767STomasz Tomasik 296c9640767STomasz Tomasik //linktitle 297c9640767STomasz Tomasik $linktitle = ''; 298c9640767STomasz Tomasik if (strlen($LN[$name]) > 0){ 299c9640767STomasz Tomasik $linktitle = $LN[$name]; 300c9640767STomasz Tomasik } else{ 301c9640767STomasz Tomasik $linktitle = hsc($name); 302c9640767STomasz Tomasik } 303c9640767STomasz Tomasik 304c9640767STomasz Tomasik //if (show flag AND ((flag exist) OR (flag not exist AND show blank flag)) 305c9640767STomasz Tomasik if (($langflag[hsc($name)] != NULL && strlen($langflag[hsc($name)]) > 0 && $this->getConf('flags')) || $this->getConf('flags') && $this->getConf('blankflag')) { 306c9640767STomasz Tomasik 307c9640767STomasz Tomasik resolve_pageid(getNS($ID),$link,$exists); 30801dd7da9SAndreas Gohr if ($div) { 309c9640767STomasz Tomasik if ($exists){ //solid box 310c9640767STomasz Tomasik $out .= ' <li><div class="li">'; 311c9640767STomasz Tomasik } else{ //50% transparent box (50% transparent flag) 312c9640767STomasz Tomasik $out .= ' <li><div class="flag_not_exists">'; 313c9640767STomasz Tomasik } 314c9640767STomasz Tomasik } 315c9640767STomasz Tomasik 316c9640767STomasz Tomasik //html_wikilink works very slow for images 317c9640767STomasz Tomasik //$flag['title'] = $langname[$name]; 318c9640767STomasz Tomasik //$flag['src'] = DOKU_URL.'lib/plugins/translation/flags/'.$langflag[$name]; 319c9640767STomasz Tomasik //$out .= html_wikilink($link,$flag); 320c9640767STomasz Tomasik 321c9640767STomasz Tomasik $out .= '<a href="'.wl($link).'"'; 322c9640767STomasz Tomasik $out .= 'title="'.$linktitle.'"'; 323c9640767STomasz Tomasik //class for image 32401dd7da9SAndreas Gohr $out .= 'class="wikilink3"'; //FIXME WTF? 325c9640767STomasz Tomasik $out .= '>'; 326c9640767STomasz Tomasik 327c9640767STomasz Tomasik //show flag 328c9640767STomasz Tomasik if ($langflag[hsc($name)] != NULL && strlen($langflag[hsc($name)]) > 0){ 329c9640767STomasz Tomasik $out .= '<img src="'.DOKU_URL.'lib/plugins/translation/flags/'.$langflag[hsc($name)].'" alt='.$linktitle.'" border="0">'; 330c9640767STomasz Tomasik } else{ //show blank flag 331c9640767STomasz Tomasik //$out .= '<img src="'.DOKU_BASE.'lib/images/blank.gif'.'" width=15 height=11 alt="'.$linktitle.'" border="0">'; 332c9640767STomasz Tomasik $out .= '<img src="'.DOKU_BASE.'lib/plugins/translation/flags/blankflag.gif'.'" width=15 height=11 alt="'.$linktitle.'" border="0">'; 333c9640767STomasz Tomasik } 334c9640767STomasz Tomasik $out .= '</a>'; 335c9640767STomasz Tomasik 33601dd7da9SAndreas Gohr } else{ //show text (also if flag not exist and blankflag=false) 33701dd7da9SAndreas Gohr if ($div) { 338c9640767STomasz Tomasik $out .= ' <li><div class="li">'; 339c9640767STomasz Tomasik } 340c9640767STomasz Tomasik $out .= html_wikilink($link,hsc($name)); 341c9640767STomasz Tomasik } 34201dd7da9SAndreas Gohr if ($div) { 343c9640767STomasz Tomasik $out .= '</div></li>'; 344c9640767STomasz Tomasik } 345c9640767STomasz Tomasik 346c9640767STomasz Tomasik return $out; 347c9640767STomasz Tomasik } 348c9640767STomasz Tomasik 34984877e9bSAndreas Gohr /** 35084877e9bSAndreas Gohr * Checks if the current page is a translation of a page 35184877e9bSAndreas Gohr * in the default language. Displays a notice when it is 35284877e9bSAndreas Gohr * older than the original page. Tries to lin to a diff 35384877e9bSAndreas Gohr * with changes on the original since the translation 35484877e9bSAndreas Gohr */ 35584877e9bSAndreas Gohr function checkage(){ 35684877e9bSAndreas Gohr global $ID; 35784877e9bSAndreas Gohr global $INFO; 35884877e9bSAndreas Gohr if(!$this->getConf('checkage')) return; 35984877e9bSAndreas Gohr if(!$INFO['exists']) return; 36084877e9bSAndreas Gohr $lng = $this->getLangPart($ID); 36184877e9bSAndreas Gohr if($lng == $this->defaultlang) return; 362af1904f9SAndreas Gohr 36384877e9bSAndreas Gohr $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/'; 36484877e9bSAndreas Gohr $idpart = preg_replace($rx,'',$ID); 36584877e9bSAndreas Gohr 36684877e9bSAndreas Gohr // compare modification times 36784877e9bSAndreas Gohr list($orig,$name) = $this->buildTransID($this->defaultlang,$idpart); 36884877e9bSAndreas Gohr $origfn = wikiFN($orig); 36984877e9bSAndreas Gohr if($INFO['lastmod'] >= @filemtime($origfn) ) return; 37084877e9bSAndreas Gohr 37184877e9bSAndreas Gohr // get revision from before translation 37284877e9bSAndreas Gohr $orev = 0; 37384877e9bSAndreas Gohr $revs = getRevisions($orig,0,100); 37484877e9bSAndreas Gohr foreach($revs as $rev){ 37584877e9bSAndreas Gohr if($rev < $INFO['lastmod']){ 37684877e9bSAndreas Gohr $orev = $rev; 37784877e9bSAndreas Gohr break; 37884877e9bSAndreas Gohr } 37984877e9bSAndreas Gohr } 38084877e9bSAndreas Gohr 38144552920SAndreas Gohr // see if the found revision still exists 38244552920SAndreas Gohr if($orev && !page_exists($orig,$orev)) $orev=0; 38344552920SAndreas Gohr 38484877e9bSAndreas Gohr // build the message and display it 385dc3fbdb9SOleksiy Zagorskyi $orig = cleanID($orig); 38684877e9bSAndreas Gohr $msg = sprintf($this->getLang('outdated'),wl($orig)); 38784877e9bSAndreas Gohr if($orev){ 38884877e9bSAndreas Gohr $msg .= sprintf(' '.$this->getLang('diff'), 38984877e9bSAndreas Gohr wl($orig,array('do'=>'diff','rev'=>$orev))); 39084877e9bSAndreas Gohr } 39100431e1eSAndreas Gohr 39200431e1eSAndreas Gohr echo '<div class="notify">'.$msg.'</div>'; 39384877e9bSAndreas Gohr } 394af1904f9SAndreas Gohr} 395