xref: /plugin/autotranslation/helper.php (revision d0bdb959cf6e219c41bb16f09cf711fdc0ac42f1)
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        $this->tns = cleanID($this->getConf('translationns'));
48af1904f9SAndreas Gohr        if($this->tns) $this->tns .= ':';
49af1904f9SAndreas Gohr    }
50af1904f9SAndreas Gohr
51af1904f9SAndreas Gohr    /**
52af1904f9SAndreas Gohr     * Check if the given ID is a translation and return the language code.
53af1904f9SAndreas Gohr     */
54af1904f9SAndreas Gohr    function getLangPart($id){
5526522e09SAndreas Gohr        list($lng) = $this->getTransParts($id);
5626522e09SAndreas Gohr        return $lng;
57af1904f9SAndreas Gohr    }
5826522e09SAndreas Gohr
5926522e09SAndreas Gohr    /**
6026522e09SAndreas Gohr     * Check if the given ID is a translation and return the language code and
6126522e09SAndreas Gohr     * the id part.
6226522e09SAndreas Gohr     */
6326522e09SAndreas Gohr    function getTransParts($id){
6426522e09SAndreas Gohr        $rx = '/^'.$this->tns.'('.join('|',$this->trans).'):(.*)/';
6526522e09SAndreas Gohr        if(preg_match($rx,$id,$match)){
6626522e09SAndreas Gohr            return array($match[1],$match[2]);
6726522e09SAndreas Gohr        }
6826522e09SAndreas Gohr        return array('',$id);
69af1904f9SAndreas Gohr    }
70af1904f9SAndreas Gohr
71af1904f9SAndreas Gohr    /**
727053cd66SAndreas Gohr     * Returns the browser language if it matches with one of the configured
737053cd66SAndreas Gohr     * languages
747053cd66SAndreas Gohr     */
757053cd66SAndreas Gohr    function getBrowserLang(){
767053cd66SAndreas Gohr        $rx = '/(^|,|:|;|-)('.join('|',$this->trans).')($|,|:|;|-)/i';
777053cd66SAndreas Gohr        if(preg_match($rx,$_SERVER['HTTP_ACCEPT_LANGUAGE'],$match)){
787053cd66SAndreas Gohr            return strtolower($match[2]);
797053cd66SAndreas Gohr        }
807053cd66SAndreas Gohr        return false;
817053cd66SAndreas Gohr    }
827053cd66SAndreas Gohr
837053cd66SAndreas Gohr    /**
847c54a0a6SAndreas Gohr     * Returns the ID and name to the wanted translation, empty
857c54a0a6SAndreas Gohr     * $lng is default lang
86af1904f9SAndreas Gohr     */
87af1904f9SAndreas Gohr    function buildTransID($lng,$idpart){
88af1904f9SAndreas Gohr        global $conf;
89af1904f9SAndreas Gohr        global $saved_conf;
90af1904f9SAndreas Gohr        if($lng){
91af1904f9SAndreas Gohr            $link = ':'.$this->tns.$lng.':'.$idpart;
92af1904f9SAndreas Gohr            $name = $lng;
93af1904f9SAndreas Gohr        }else{
94af1904f9SAndreas Gohr            $link = ':'.$this->tns.$idpart;
95af1904f9SAndreas Gohr            if(!$conf['lang_before_translation']){
96af1904f9SAndreas Gohr              $name = $conf['lang'];
97af1904f9SAndreas Gohr            } else {
98af1904f9SAndreas Gohr              $name = $conf['lang_before_translation'];
99af1904f9SAndreas Gohr            }
100af1904f9SAndreas Gohr        }
101af1904f9SAndreas Gohr        return array($link,$name);
102af1904f9SAndreas Gohr    }
103af1904f9SAndreas Gohr
1041469199dSAndreas Gohr    /**
10584877e9bSAndreas Gohr     * Check if current ID should be translated and any GUI
10684877e9bSAndreas Gohr     * should be shown
10784877e9bSAndreas Gohr     */
10884877e9bSAndreas Gohr    function istranslatable($id,$checkact=true){
10984877e9bSAndreas Gohr        global $ACT;
11084877e9bSAndreas Gohr
11184877e9bSAndreas Gohr        if($checkact && $ACT != 'show') return false;
11284877e9bSAndreas Gohr        if($this->tns && strpos($id,$this->tns) !== 0) return false;
11384877e9bSAndreas Gohr        $skiptrans = trim($this->getConf('skiptrans'));
11484877e9bSAndreas Gohr        if($skiptrans &&  preg_match('/'.$skiptrans.'/ui',':'.$id)) return false;
11584877e9bSAndreas Gohr        $meta = p_get_metadata($id);
11684877e9bSAndreas Gohr        if($meta['plugin']['translation']['notrans']) return false;
11784877e9bSAndreas Gohr
11884877e9bSAndreas Gohr        return true;
11984877e9bSAndreas Gohr    }
12084877e9bSAndreas Gohr
12101dd7da9SAndreas Gohr    /**
12201dd7da9SAndreas Gohr     * Return the (localized) about link
12301dd7da9SAndreas Gohr     */
12401dd7da9SAndreas Gohr    function showAbout() {
125c9640767STomasz Tomasik        global $ID;
126c9640767STomasz Tomasik        global $conf;
127c9640767STomasz Tomasik        global $INFO;
128c9640767STomasz Tomasik
129*d0bdb959SAndreas Gohr        $this->checkage(); //FIXME why is this here?
130c9640767STomasz Tomasik
131*d0bdb959SAndreas Gohr        $about = $this->getConf('about');
132*d0bdb959SAndreas Gohr        if($this->getConf('localabout')){
133*d0bdb959SAndreas Gohr            list($lc,$idpart) = $this->getTransParts($about);
134*d0bdb959SAndreas Gohr            list($about,$name) = $this->buildTransID($conf['lang'],$idpart);
135*d0bdb959SAndreas Gohr            $about = cleanID($about);
136*d0bdb959SAndreas Gohr        }
137c9640767STomasz Tomasik
138c9640767STomasz Tomasik        $out = '';
139c9640767STomasz Tomasik        $out .= '<sup>';
140*d0bdb959SAndreas Gohr        $out .= html_wikilink($about,'?');
141c9640767STomasz Tomasik        $out .= '</sup>';
142c9640767STomasz Tomasik
143c9640767STomasz Tomasik        return $out;
144c9640767STomasz Tomasik    }
145c9640767STomasz Tomasik
14684877e9bSAndreas Gohr    /**
1471469199dSAndreas Gohr     * Displays the available and configured translations. Needs to be placed in the template.
1481469199dSAndreas Gohr     */
1491469199dSAndreas Gohr    function showTranslations(){
1501469199dSAndreas Gohr        global $ID;
1511469199dSAndreas Gohr        global $conf;
1521469199dSAndreas Gohr        global $INFO;
1531469199dSAndreas Gohr
15484877e9bSAndreas Gohr        if(!$this->istranslatable($ID)) return;
15584877e9bSAndreas Gohr
15684877e9bSAndreas Gohr        $this->checkage();
1571469199dSAndreas Gohr
15839ecab8bSAndreas Gohr        $LN = confToHash(dirname(__FILE__).'/lang/langnames.txt');
15939ecab8bSAndreas Gohr
1601469199dSAndreas Gohr        $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/';
1611469199dSAndreas Gohr        $idpart = preg_replace($rx,'',$ID);
1621469199dSAndreas Gohr
1631469199dSAndreas Gohr        $out  = '<div class="plugin_translation">';
164c9640767STomasz Tomasik
165c9640767STomasz Tomasik        //show text
166c9640767STomasz Tomasik        if ($this->getConf('description')){
1671469199dSAndreas Gohr            $out .= '<span>'.$this->getLang('translations');
168c9640767STomasz Tomasik            if ($this->getConf('showabout')) $out .= $this->showAbout();
1691469199dSAndreas Gohr            $out .= ':</span> ';
170c9640767STomasz Tomasik        }
1711469199dSAndreas Gohr
17201dd7da9SAndreas Gohr        if($this->getConf('dropdown')){ // use dropdown fixme move to own functions
1731469199dSAndreas Gohr            if($INFO['exists']){
1741469199dSAndreas Gohr                $class = 'wikilink1';
1751469199dSAndreas Gohr            }else{
1761469199dSAndreas Gohr                $class = 'wikilink2';
1771469199dSAndreas Gohr            }
178c9640767STomasz Tomasik
17901dd7da9SAndreas Gohr            $out2 = ""; //FIXME ugly name
1801469199dSAndreas Gohr            foreach($this->trans as $t){
1811469199dSAndreas Gohr                list($link,$name) = $this->buildTransID($t,$idpart);
1821469199dSAndreas Gohr                $link = cleanID($link);
1831469199dSAndreas Gohr                if($ID == $link){
1841469199dSAndreas Gohr                    $sel = ' selected="selected"';
18501dd7da9SAndreas Gohr                    if($this->getConf('dropdown2')) { //FIXME ugly name
186c9640767STomasz Tomasik                        $out .= $this->makecountrylink($LN, $idpart, $t, false);
187c9640767STomasz Tomasik                        $out .= "&nbsp;";
188c9640767STomasz Tomasik                    }
1891469199dSAndreas Gohr                }else{
1901469199dSAndreas Gohr                    $sel = '';
1911469199dSAndreas Gohr                }
1921469199dSAndreas Gohr                if(page_exists($link,'',false)){
1931469199dSAndreas Gohr                    $class = 'wikilink1';
1941469199dSAndreas Gohr                }else{
1951469199dSAndreas Gohr                    $class = 'wikilink2';
1961469199dSAndreas Gohr                }
197c9640767STomasz Tomasik
198c9640767STomasz Tomasik                //linktitle
199c9640767STomasz Tomasik                $linktitle = '';
200c9640767STomasz Tomasik                if (strlen($LN[$name]) > 0){
201c9640767STomasz Tomasik                    $linktitle = $LN[$name];
202c9640767STomasz Tomasik                } else{
203c9640767STomasz Tomasik                    $linktitle = hsc($name);
2041469199dSAndreas Gohr                }
205c9640767STomasz Tomasik
206c9640767STomasz Tomasik                $out2 .= '<option value="'.$link.'"'.$sel.' class="'.$class.'" title="'.$linktitle.'">'.hsc($name).'</option>';
207c9640767STomasz Tomasik            }
208c9640767STomasz Tomasik            $out .= '<form action="'.wl().'" id="translation__dropdown">';
209c9640767STomasz Tomasik            $out .= '<select name="id" class="'.$class.'">';
210c9640767STomasz Tomasik            $out .= $out2;
2111469199dSAndreas Gohr            $out .= '</select>';
2121469199dSAndreas Gohr            $out .= '<input name="go" type="submit" value="&rarr;" />';
2131469199dSAndreas Gohr            $out .= '</form>';
214c9640767STomasz Tomasik
215c9640767STomasz Tomasik            //link to about (right)
216c9640767STomasz Tomasik            if (!$this->getConf('description') && $this->getConf('showabout')) {
217c9640767STomasz Tomasik                $out .= '&nbsp';
218c9640767STomasz Tomasik                $out .= $this->showAbout();
21939ecab8bSAndreas Gohr            }
220c9640767STomasz Tomasik        }else{ // use list
221c9640767STomasz Tomasik            $out .= '<ul>';
222c9640767STomasz Tomasik
22301dd7da9SAndreas Gohr            // FIXME what's this?
224c9640767STomasz Tomasik            if (!$this->getConf('description') && $this->getConf('showabout')) {
225c9640767STomasz Tomasik                $out .= '&nbsp';
226c9640767STomasz Tomasik                $out .= $this->showAbout();
227c9640767STomasz Tomasik            }
228c9640767STomasz Tomasik
229c9640767STomasz Tomasik            foreach($this->trans as $t){
230c9640767STomasz Tomasik                $out .= $this->makecountrylink($LN, $idpart, $t, true);
2311469199dSAndreas Gohr            }
2321469199dSAndreas Gohr            $out .= '</ul>';
2331469199dSAndreas Gohr        }
2341469199dSAndreas Gohr
2351469199dSAndreas Gohr        $out .= '</div>';
2361469199dSAndreas Gohr
2371469199dSAndreas Gohr        return $out;
2381469199dSAndreas Gohr    }
239af1904f9SAndreas Gohr
24001dd7da9SAndreas Gohr    /**
24101dd7da9SAndreas Gohr     * Create the link or option for a single translation
24201dd7da9SAndreas Gohr     *
24301dd7da9SAndreas Gohr     * @fixme bad name - translations are not about countries
24401dd7da9SAndreas Gohr     * @param $LN string      The language
24501dd7da9SAndreas Gohr     * @param $idpart string  The ID of the translated page
24601dd7da9SAndreas Gohr     * @param $t  FIXME
24701dd7da9SAndreas Gohr     * @param $div bool  true for lists, false for dropdown FIXME
24801dd7da9SAndreas Gohr     * @returns FIXME
24901dd7da9SAndreas Gohr     */
25001dd7da9SAndreas Gohr    function makecountrylink($LN, $idpart, $t, $div) {
251c9640767STomasz Tomasik        global $ID;
252c9640767STomasz Tomasik        global $conf;
253c9640767STomasz Tomasik        global $INFO;
254c9640767STomasz Tomasik
255c9640767STomasz Tomasik        require(DOKU_PLUGIN.'translation/flags/langnames.php');
256c9640767STomasz Tomasik
257c9640767STomasz Tomasik        list($link,$name) = $this->buildTransID($t,$idpart);
258c9640767STomasz Tomasik        $link = cleanID($link);
259c9640767STomasz Tomasik        if(page_exists($link,'',false)){
260c9640767STomasz Tomasik            $class = 'wikilink1';
261c9640767STomasz Tomasik        }else{
262c9640767STomasz Tomasik            $class = 'wikilink2';
263c9640767STomasz Tomasik        }
264c9640767STomasz Tomasik
265c9640767STomasz Tomasik        //linktitle
266c9640767STomasz Tomasik        $linktitle = '';
267c9640767STomasz Tomasik        if (strlen($LN[$name]) > 0){
268c9640767STomasz Tomasik            $linktitle = $LN[$name];
269c9640767STomasz Tomasik        } else{
270c9640767STomasz Tomasik            $linktitle = hsc($name);
271c9640767STomasz Tomasik        }
272c9640767STomasz Tomasik
273c9640767STomasz Tomasik        //if (show flag AND ((flag exist) OR (flag not exist AND show blank flag))
274c9640767STomasz Tomasik        if (($langflag[hsc($name)] != NULL && strlen($langflag[hsc($name)]) > 0 && $this->getConf('flags')) || $this->getConf('flags') && $this->getConf('blankflag')) {
275c9640767STomasz Tomasik
276c9640767STomasz Tomasik            resolve_pageid(getNS($ID),$link,$exists);
27701dd7da9SAndreas Gohr            if ($div) {
278c9640767STomasz Tomasik                if ($exists){ //solid box
279c9640767STomasz Tomasik                    $out .= '  <li><div class="li">';
280c9640767STomasz Tomasik                } else{ //50% transparent box (50% transparent flag)
281c9640767STomasz Tomasik                    $out .= '  <li><div class="flag_not_exists">';
282c9640767STomasz Tomasik                }
283c9640767STomasz Tomasik            }
284c9640767STomasz Tomasik
285c9640767STomasz Tomasik            //html_wikilink works very slow for images
286c9640767STomasz Tomasik            //$flag['title'] = $langname[$name];
287c9640767STomasz Tomasik            //$flag['src'] = DOKU_URL.'lib/plugins/translation/flags/'.$langflag[$name];
288c9640767STomasz Tomasik            //$out .= html_wikilink($link,$flag);
289c9640767STomasz Tomasik
290c9640767STomasz Tomasik            $out .= '<a href="'.wl($link).'"';
291c9640767STomasz Tomasik            $out .= 'title="'.$linktitle.'"';
292c9640767STomasz Tomasik            //class for image
29301dd7da9SAndreas Gohr            $out .= 'class="wikilink3"'; //FIXME WTF?
294c9640767STomasz Tomasik            $out .= '>';
295c9640767STomasz Tomasik
296c9640767STomasz Tomasik            //show flag
297c9640767STomasz Tomasik            if ($langflag[hsc($name)] != NULL && strlen($langflag[hsc($name)]) > 0){
298c9640767STomasz Tomasik                $out .= '<img src="'.DOKU_URL.'lib/plugins/translation/flags/'.$langflag[hsc($name)].'" alt='.$linktitle.'" border="0">';
299c9640767STomasz Tomasik            } else{ //show blank flag
300c9640767STomasz Tomasik                //$out .= '<img src="'.DOKU_BASE.'lib/images/blank.gif'.'" width=15 height=11 alt="'.$linktitle.'" border="0">';
301c9640767STomasz Tomasik                $out .= '<img src="'.DOKU_BASE.'lib/plugins/translation/flags/blankflag.gif'.'" width=15 height=11 alt="'.$linktitle.'" border="0">';
302c9640767STomasz Tomasik            }
303c9640767STomasz Tomasik            $out .= '</a>';
304c9640767STomasz Tomasik
30501dd7da9SAndreas Gohr        } else{ //show text (also if flag not exist and blankflag=false)
30601dd7da9SAndreas Gohr            if ($div) {
307c9640767STomasz Tomasik                $out .= '  <li><div class="li">';
308c9640767STomasz Tomasik            }
309c9640767STomasz Tomasik            $out .= html_wikilink($link,hsc($name));
310c9640767STomasz Tomasik        }
31101dd7da9SAndreas Gohr        if ($div) {
312c9640767STomasz Tomasik            $out .= '</div></li>';
313c9640767STomasz Tomasik        }
314c9640767STomasz Tomasik
315c9640767STomasz Tomasik        return $out;
316c9640767STomasz Tomasik    }
317c9640767STomasz Tomasik
31884877e9bSAndreas Gohr    /**
31984877e9bSAndreas Gohr     * Checks if the current page is a translation of a page
32084877e9bSAndreas Gohr     * in the default language. Displays a notice when it is
32184877e9bSAndreas Gohr     * older than the original page. Tries to lin to a diff
32284877e9bSAndreas Gohr     * with changes on the original since the translation
32384877e9bSAndreas Gohr     */
32484877e9bSAndreas Gohr    function checkage(){
32584877e9bSAndreas Gohr        global $ID;
32684877e9bSAndreas Gohr        global $INFO;
32784877e9bSAndreas Gohr        if(!$this->getConf('checkage')) return;
32884877e9bSAndreas Gohr        if(!$INFO['exists']) return;
32984877e9bSAndreas Gohr        $lng = $this->getLangPart($ID);
33084877e9bSAndreas Gohr        if($lng == $this->defaultlang) return;
331af1904f9SAndreas Gohr
33284877e9bSAndreas Gohr        $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/';
33384877e9bSAndreas Gohr        $idpart = preg_replace($rx,'',$ID);
33484877e9bSAndreas Gohr
33584877e9bSAndreas Gohr        // compare modification times
33684877e9bSAndreas Gohr        list($orig,$name) = $this->buildTransID($this->defaultlang,$idpart);
33784877e9bSAndreas Gohr        $origfn = wikiFN($orig);
33884877e9bSAndreas Gohr        if($INFO['lastmod'] >= @filemtime($origfn) ) return;
33984877e9bSAndreas Gohr
34084877e9bSAndreas Gohr        // get revision from before translation
34184877e9bSAndreas Gohr        $orev = 0;
34284877e9bSAndreas Gohr        $revs = getRevisions($orig,0,100);
34384877e9bSAndreas Gohr        foreach($revs as $rev){
34484877e9bSAndreas Gohr            if($rev < $INFO['lastmod']){
34584877e9bSAndreas Gohr                $orev = $rev;
34684877e9bSAndreas Gohr                break;
34784877e9bSAndreas Gohr            }
34884877e9bSAndreas Gohr        }
34984877e9bSAndreas Gohr
35044552920SAndreas Gohr        // see if the found revision still exists
35144552920SAndreas Gohr        if($orev && !page_exists($orig,$orev)) $orev=0;
35244552920SAndreas Gohr
35384877e9bSAndreas Gohr        // build the message and display it
354dc3fbdb9SOleksiy Zagorskyi        $orig = cleanID($orig);
35584877e9bSAndreas Gohr        $msg = sprintf($this->getLang('outdated'),wl($orig));
35684877e9bSAndreas Gohr        if($orev){
35784877e9bSAndreas Gohr            $msg .= sprintf(' '.$this->getLang('diff'),
35884877e9bSAndreas Gohr                    wl($orig,array('do'=>'diff','rev'=>$orev)));
35984877e9bSAndreas Gohr        }
36000431e1eSAndreas Gohr
36100431e1eSAndreas Gohr        echo '<div class="notify">'.$msg.'</div>';
36284877e9bSAndreas Gohr    }
363af1904f9SAndreas Gohr}
364