1<?php 2/** 3 * Translation Plugin: Simple multilanguage plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11 12class helper_plugin_translation extends DokuWiki_Plugin { 13 var $trans = array(); 14 var $tns = ''; 15 var $defaultlang = ''; 16 17 /** 18 * Initialize 19 */ 20 function helper_plugin_translation(){ 21 global $conf; 22 require_once(DOKU_INC.'inc/pageutils.php'); 23 require_once(DOKU_INC.'inc/utf8.php'); 24 25 // load wanted translation into array 26 $this->trans = strtolower(str_replace(',',' ',$this->getConf('translations'))); 27 $this->trans = array_unique(array_filter(explode(' ',$this->trans))); 28 sort($this->trans); 29 30 // get default translation 31 if(!$conf['lang_before_translation']){ 32 $dfl = $conf['lang']; 33 } else { 34 $dfl = $conf['lang_before_translation']; 35 } 36 if(in_array($dfl,$this->trans)){ 37 $this->defaultlang = $dfl; 38 }else{ 39 $this->defaultlang = ''; 40 array_unshift($this->trans,''); 41 } 42 43 44 $this->tns = cleanID($this->getConf('translationns')); 45 if($this->tns) $this->tns .= ':'; 46 } 47 48 /** 49 * Check if the given ID is a translation and return the language code. 50 */ 51 function getLangPart($id){ 52 $rx = '/^'.$this->tns.'('.join('|',$this->trans).'):/'; 53 if(preg_match($rx,$id,$match)){ 54 return $match[1]; 55 } 56 return ''; 57 } 58 59 /** 60 * Returns the browser language if it matches with one of the configured 61 * languages 62 */ 63 function getBrowserLang(){ 64 $rx = '/(^|,|:|;|-)('.join('|',$this->trans).')($|,|:|;|-)/i'; 65 if(preg_match($rx,$_SERVER['HTTP_ACCEPT_LANGUAGE'],$match)){ 66 return strtolower($match[2]); 67 } 68 return false; 69 } 70 71 72 /** 73 * Returns the ID and name to the wanted translation, empty 74 * $lng is default lang 75 */ 76 function buildTransID($lng,$idpart){ 77 global $conf; 78 global $saved_conf; 79 if($lng){ 80 $link = ':'.$this->tns.$lng.':'.$idpart; 81 $name = $lng; 82 }else{ 83 $link = ':'.$this->tns.$idpart; 84 if(!$conf['lang_before_translation']){ 85 $name = $conf['lang']; 86 } else { 87 $name = $conf['lang_before_translation']; 88 } 89 } 90 return array($link,$name); 91 } 92 93 /** 94 * Check if current ID should be translated and any GUI 95 * should be shown 96 */ 97 function istranslatable($id,$checkact=true){ 98 global $ACT; 99 100 if($checkact && $ACT != 'show') return false; 101 if($this->tns && strpos($id,$this->tns) !== 0) return false; 102 $skiptrans = trim($this->getConf('skiptrans')); 103 if($skiptrans && preg_match('/'.$skiptrans.'/ui',':'.$id)) return false; 104 $meta = p_get_metadata($id); 105 if($meta['plugin']['translation']['notrans']) return false; 106 107 return true; 108 } 109 110 /** 111 * Displays the available and configured translations. Needs to be placed in the template. 112 */ 113 function showTranslations(){ 114 global $ID; 115 global $conf; 116 global $INFO; 117 118 if(!$this->istranslatable($ID)) return; 119 120 $this->checkage(); 121 122 $LN = confToHash(dirname(__FILE__).'/lang/langnames.txt'); 123 124 $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/'; 125 $idpart = preg_replace($rx,'',$ID); 126 127 $out = '<div class="plugin_translation">'; 128 $out .= '<span>'.$this->getLang('translations'); 129 if($this->getConf('about')){ 130 $out .= '<sup>'.html_wikilink($this->getConf('about'),'?').'</sup>'; 131 } 132 $out .= ':</span> '; 133 134 if($this->getConf('dropdown')){ // use dropdown 135 if($INFO['exists']){ 136 $class = 'wikilink1'; 137 }else{ 138 $class = 'wikilink2'; 139 } 140 $out .= '<form action="'.wl().'" id="translation__dropdown">'; 141 $out .= '<select name="id" class="'.$class.'">'; 142 foreach($this->trans as $t){ 143 list($link,$name) = $this->buildTransID($t,$idpart); 144 $link = cleanID($link); 145 if($ID == $link){ 146 $sel = ' selected="selected"'; 147 }else{ 148 $sel = ''; 149 } 150 if(page_exists($link,'',false)){ 151 $class = 'wikilink1'; 152 }else{ 153 $class = 'wikilink2'; 154 } 155 $out .= '<option value="'.$link.'"'.$sel.' class="'.$class.'" title="'.$LN[$name].'">'.hsc($name).'</option>'; 156 } 157 $out .= '</select>'; 158 $out .= '<input name="go" type="submit" value="→" />'; 159 $out .= '</form>'; 160 }else{ // use list 161 $out .= '<ul>'; 162 foreach($this->trans as $t){ 163 list($link,$name) = $this->buildTransID($t,$idpart); 164 $link = cleanID($link); 165 if(page_exists($link,'',false)){ 166 $class = 'wikilink1'; 167 }else{ 168 $class = 'wikilink2'; 169 } 170 $out .= ' <li><div class="li"><a href="'.wl($link).'" class="'.$class.'" title="'.$LN[$name].'">'.hsc($name).'</a></div></li>'; 171 } 172 $out .= '</ul>'; 173 } 174 175 $out .= '</div>'; 176 177 return $out; 178 } 179 180 /** 181 * Checks if the current page is a translation of a page 182 * in the default language. Displays a notice when it is 183 * older than the original page. Tries to lin to a diff 184 * with changes on the original since the translation 185 */ 186 function checkage(){ 187 global $ID; 188 global $INFO; 189 if(!$this->getConf('checkage')) return; 190 if(!$INFO['exists']) return; 191 $lng = $this->getLangPart($ID); 192 if($lng == $this->defaultlang) return; 193 194 $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/'; 195 $idpart = preg_replace($rx,'',$ID); 196 197 // compare modification times 198 list($orig,$name) = $this->buildTransID($this->defaultlang,$idpart); 199 $origfn = wikiFN($orig); 200 if($INFO['lastmod'] >= @filemtime($origfn) ) return; 201 202 // get revision from before translation 203 $orev = 0; 204 $revs = getRevisions($orig,0,100); 205 foreach($revs as $rev){ 206 if($rev < $INFO['lastmod']){ 207 $orev = $rev; 208 break; 209 } 210 } 211 212 // see if the found revision still exists 213 if($orev && !page_exists($orig,$orev)) $orev=0; 214 215 // build the message and display it 216 $orig = cleanID($orig); 217 $msg = sprintf($this->getLang('outdated'),wl($orig)); 218 if($orev){ 219 $msg .= sprintf(' '.$this->getLang('diff'), 220 wl($orig,array('do'=>'diff','rev'=>$orev))); 221 } 222 223 echo '<div class="notify">'.$msg.'</div>'; 224 } 225} 226