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 = ''; 16af1904f9SAndreas Gohr 17af1904f9SAndreas Gohr /** 18af1904f9SAndreas Gohr * Initialize 19af1904f9SAndreas Gohr */ 20af1904f9SAndreas Gohr function helper_plugin_translation(){ 217c54a0a6SAndreas Gohr global $conf; 22af1904f9SAndreas Gohr require_once(DOKU_INC.'inc/pageutils.php'); 23af1904f9SAndreas Gohr require_once(DOKU_INC.'inc/utf8.php'); 24af1904f9SAndreas Gohr 25af1904f9SAndreas Gohr // load wanted translation into array 26af1904f9SAndreas Gohr $this->trans = strtolower(str_replace(',',' ',$this->getConf('translations'))); 27af1904f9SAndreas Gohr $this->trans = array_unique(array_filter(explode(' ',$this->trans))); 28af1904f9SAndreas Gohr sort($this->trans); 297c54a0a6SAndreas Gohr 307c54a0a6SAndreas Gohr // get default translation 317c54a0a6SAndreas Gohr if(!$conf['lang_before_translation']){ 327c54a0a6SAndreas Gohr $dfl = $conf['lang']; 337c54a0a6SAndreas Gohr } else { 347c54a0a6SAndreas Gohr $dfl = $conf['lang_before_translation']; 357c54a0a6SAndreas Gohr } 367c54a0a6SAndreas Gohr if(in_array($dfl,$this->trans)){ 377c54a0a6SAndreas Gohr $this->defaultlang = $dfl; 387c54a0a6SAndreas Gohr }else{ 397c54a0a6SAndreas Gohr $this->defaultlang = ''; 40af1904f9SAndreas Gohr array_unshift($this->trans,''); 417c54a0a6SAndreas Gohr } 427c54a0a6SAndreas Gohr 43af1904f9SAndreas Gohr 44af1904f9SAndreas Gohr $this->tns = cleanID($this->getConf('translationns')); 45af1904f9SAndreas Gohr if($this->tns) $this->tns .= ':'; 46af1904f9SAndreas Gohr } 47af1904f9SAndreas Gohr 48af1904f9SAndreas Gohr /** 49af1904f9SAndreas Gohr * Check if the given ID is a translation and return the language code. 50af1904f9SAndreas Gohr */ 51af1904f9SAndreas Gohr function getLangPart($id){ 52af1904f9SAndreas Gohr $rx = '/^'.$this->tns.'('.join('|',$this->trans).'):/'; 53af1904f9SAndreas Gohr if(preg_match($rx,$id,$match)){ 54af1904f9SAndreas Gohr return $match[1]; 55af1904f9SAndreas Gohr } 56af1904f9SAndreas Gohr return ''; 57af1904f9SAndreas Gohr } 58af1904f9SAndreas Gohr 59af1904f9SAndreas Gohr /** 607053cd66SAndreas Gohr * Returns the browser language if it matches with one of the configured 617053cd66SAndreas Gohr * languages 627053cd66SAndreas Gohr */ 637053cd66SAndreas Gohr function getBrowserLang(){ 647053cd66SAndreas Gohr $rx = '/(^|,|:|;|-)('.join('|',$this->trans).')($|,|:|;|-)/i'; 657053cd66SAndreas Gohr if(preg_match($rx,$_SERVER['HTTP_ACCEPT_LANGUAGE'],$match)){ 667053cd66SAndreas Gohr return strtolower($match[2]); 677053cd66SAndreas Gohr } 687053cd66SAndreas Gohr return false; 697053cd66SAndreas Gohr } 707053cd66SAndreas Gohr 717053cd66SAndreas Gohr 727053cd66SAndreas Gohr /** 737c54a0a6SAndreas Gohr * Returns the ID and name to the wanted translation, empty 747c54a0a6SAndreas Gohr * $lng is default lang 75af1904f9SAndreas Gohr */ 76af1904f9SAndreas Gohr function buildTransID($lng,$idpart){ 77af1904f9SAndreas Gohr global $conf; 78af1904f9SAndreas Gohr global $saved_conf; 79af1904f9SAndreas Gohr if($lng){ 80af1904f9SAndreas Gohr $link = ':'.$this->tns.$lng.':'.$idpart; 81af1904f9SAndreas Gohr $name = $lng; 82af1904f9SAndreas Gohr }else{ 83af1904f9SAndreas Gohr $link = ':'.$this->tns.$idpart; 84af1904f9SAndreas Gohr if(!$conf['lang_before_translation']){ 85af1904f9SAndreas Gohr $name = $conf['lang']; 86af1904f9SAndreas Gohr } else { 87af1904f9SAndreas Gohr $name = $conf['lang_before_translation']; 88af1904f9SAndreas Gohr } 89af1904f9SAndreas Gohr } 90af1904f9SAndreas Gohr return array($link,$name); 91af1904f9SAndreas Gohr } 92af1904f9SAndreas Gohr 931469199dSAndreas Gohr /** 9484877e9bSAndreas Gohr * Check if current ID should be translated and any GUI 9584877e9bSAndreas Gohr * should be shown 9684877e9bSAndreas Gohr */ 9784877e9bSAndreas Gohr function istranslatable($id,$checkact=true){ 9884877e9bSAndreas Gohr global $ACT; 9984877e9bSAndreas Gohr 10084877e9bSAndreas Gohr if($checkact && $ACT != 'show') return false; 10184877e9bSAndreas Gohr if($this->tns && strpos($id,$this->tns) !== 0) return false; 10284877e9bSAndreas Gohr $skiptrans = trim($this->getConf('skiptrans')); 10384877e9bSAndreas Gohr if($skiptrans && preg_match('/'.$skiptrans.'/ui',':'.$id)) return false; 10484877e9bSAndreas Gohr $meta = p_get_metadata($id); 10584877e9bSAndreas Gohr if($meta['plugin']['translation']['notrans']) return false; 10684877e9bSAndreas Gohr 10784877e9bSAndreas Gohr return true; 10884877e9bSAndreas Gohr } 10984877e9bSAndreas Gohr 11084877e9bSAndreas Gohr /** 1111469199dSAndreas Gohr * Displays the available and configured translations. Needs to be placed in the template. 1121469199dSAndreas Gohr */ 1131469199dSAndreas Gohr function showTranslations(){ 1141469199dSAndreas Gohr global $ID; 1151469199dSAndreas Gohr global $conf; 1161469199dSAndreas Gohr global $INFO; 1171469199dSAndreas Gohr 11884877e9bSAndreas Gohr if(!$this->istranslatable($ID)) return; 11984877e9bSAndreas Gohr 12084877e9bSAndreas Gohr $this->checkage(); 1211469199dSAndreas Gohr 122*39ecab8bSAndreas Gohr $LN = confToHash(dirname(__FILE__).'/lang/langnames.txt'); 123*39ecab8bSAndreas Gohr 1241469199dSAndreas Gohr $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/'; 1251469199dSAndreas Gohr $idpart = preg_replace($rx,'',$ID); 1261469199dSAndreas Gohr 1271469199dSAndreas Gohr $out = '<div class="plugin_translation">'; 1281469199dSAndreas Gohr $out .= '<span>'.$this->getLang('translations'); 1291469199dSAndreas Gohr if($this->getConf('about')){ 1301469199dSAndreas Gohr $out .= '<sup>'.html_wikilink($this->getConf('about'),'?').'</sup>'; 1311469199dSAndreas Gohr } 1321469199dSAndreas Gohr $out .= ':</span> '; 1331469199dSAndreas Gohr 1341469199dSAndreas Gohr if($this->getConf('dropdown')){ // use dropdown 1351469199dSAndreas Gohr if($INFO['exists']){ 1361469199dSAndreas Gohr $class = 'wikilink1'; 1371469199dSAndreas Gohr }else{ 1381469199dSAndreas Gohr $class = 'wikilink2'; 1391469199dSAndreas Gohr } 1401469199dSAndreas Gohr $out .= '<form action="'.wl().'" id="translation__dropdown">'; 1411469199dSAndreas Gohr $out .= '<select name="id" class="'.$class.'">'; 1421469199dSAndreas Gohr foreach($this->trans as $t){ 1431469199dSAndreas Gohr list($link,$name) = $this->buildTransID($t,$idpart); 1441469199dSAndreas Gohr $link = cleanID($link); 1451469199dSAndreas Gohr if($ID == $link){ 1461469199dSAndreas Gohr $sel = ' selected="selected"'; 1471469199dSAndreas Gohr }else{ 1481469199dSAndreas Gohr $sel = ''; 1491469199dSAndreas Gohr } 1501469199dSAndreas Gohr if(page_exists($link,'',false)){ 1511469199dSAndreas Gohr $class = 'wikilink1'; 1521469199dSAndreas Gohr }else{ 1531469199dSAndreas Gohr $class = 'wikilink2'; 1541469199dSAndreas Gohr } 155*39ecab8bSAndreas Gohr $out .= '<option value="'.$link.'"'.$sel.' class="'.$class.'" title="'.$LN[$name].'">'.hsc($name).'</option>'; 1561469199dSAndreas Gohr } 1571469199dSAndreas Gohr $out .= '</select>'; 1581469199dSAndreas Gohr $out .= '<input name="go" type="submit" value="→" />'; 1591469199dSAndreas Gohr $out .= '</form>'; 1601469199dSAndreas Gohr }else{ // use list 1611469199dSAndreas Gohr $out .= '<ul>'; 1621469199dSAndreas Gohr foreach($this->trans as $t){ 1631469199dSAndreas Gohr list($link,$name) = $this->buildTransID($t,$idpart); 164*39ecab8bSAndreas Gohr if(page_exists($link,'',false)){ 165*39ecab8bSAndreas Gohr $class = 'wikilink1'; 166*39ecab8bSAndreas Gohr }else{ 167*39ecab8bSAndreas Gohr $class = 'wikilink2'; 168*39ecab8bSAndreas Gohr } 169*39ecab8bSAndreas Gohr $out .= ' <li><div class="li"><a href="'.wl($link).'" class="'.$class.'" title="'.$LN[$name].'">'.hsc($name).'</a></div></li>'; 1701469199dSAndreas Gohr } 1711469199dSAndreas Gohr $out .= '</ul>'; 1721469199dSAndreas Gohr } 1731469199dSAndreas Gohr 1741469199dSAndreas Gohr $out .= '</div>'; 1751469199dSAndreas Gohr 1761469199dSAndreas Gohr return $out; 1771469199dSAndreas Gohr } 178af1904f9SAndreas Gohr 17984877e9bSAndreas Gohr /** 18084877e9bSAndreas Gohr * Checks if the current page is a translation of a page 18184877e9bSAndreas Gohr * in the default language. Displays a notice when it is 18284877e9bSAndreas Gohr * older than the original page. Tries to lin to a diff 18384877e9bSAndreas Gohr * with changes on the original since the translation 18484877e9bSAndreas Gohr */ 18584877e9bSAndreas Gohr function checkage(){ 18684877e9bSAndreas Gohr global $ID; 18784877e9bSAndreas Gohr global $INFO; 18884877e9bSAndreas Gohr if(!$this->getConf('checkage')) return; 18984877e9bSAndreas Gohr if(!$INFO['exists']) return; 19084877e9bSAndreas Gohr $lng = $this->getLangPart($ID); 19184877e9bSAndreas Gohr if($lng == $this->defaultlang) return; 192af1904f9SAndreas Gohr 19384877e9bSAndreas Gohr $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/'; 19484877e9bSAndreas Gohr $idpart = preg_replace($rx,'',$ID); 19584877e9bSAndreas Gohr 19684877e9bSAndreas Gohr // compare modification times 19784877e9bSAndreas Gohr list($orig,$name) = $this->buildTransID($this->defaultlang,$idpart); 19884877e9bSAndreas Gohr $origfn = wikiFN($orig); 19984877e9bSAndreas Gohr if($INFO['lastmod'] >= @filemtime($origfn) ) return; 20084877e9bSAndreas Gohr 20184877e9bSAndreas Gohr // get revision from before translation 20284877e9bSAndreas Gohr $orev = 0; 20384877e9bSAndreas Gohr $revs = getRevisions($orig,0,100); 20484877e9bSAndreas Gohr foreach($revs as $rev){ 20584877e9bSAndreas Gohr if($rev < $INFO['lastmod']){ 20684877e9bSAndreas Gohr $orev = $rev; 20784877e9bSAndreas Gohr break; 20884877e9bSAndreas Gohr } 20984877e9bSAndreas Gohr } 21084877e9bSAndreas Gohr 21144552920SAndreas Gohr // see if the found revision still exists 21244552920SAndreas Gohr if($orev && !page_exists($orig,$orev)) $orev=0; 21344552920SAndreas Gohr 21484877e9bSAndreas Gohr // build the message and display it 21584877e9bSAndreas Gohr $msg = sprintf($this->getLang('outdated'),wl($orig)); 21684877e9bSAndreas Gohr if($orev){ 21784877e9bSAndreas Gohr $msg .= sprintf(' '.$this->getLang('diff'), 21884877e9bSAndreas Gohr wl($orig,array('do'=>'diff','rev'=>$orev))); 21984877e9bSAndreas Gohr } 22000431e1eSAndreas Gohr 22100431e1eSAndreas Gohr echo '<div class="notify">'.$msg.'</div>'; 22284877e9bSAndreas Gohr } 223af1904f9SAndreas Gohr} 224