xref: /plugin/autotranslation/helper.php (revision 8ab229792237901c1d8f5deb82283d70b1df8a43)
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
1225fca7bdSGerry Weißbachclass helper_plugin_autotranslation extends DokuWiki_Plugin {
135ceaa3d5SGerry Weißbach
145ceaa3d5SGerry Weißbach    public $translations = array();
155ceaa3d5SGerry Weißbach    public $translationNs = '';
165ceaa3d5SGerry Weißbach    public $defaultlang = '';
175ceaa3d5SGerry Weißbach
185ceaa3d5SGerry Weißbach    private $opts = array(); // display options
195ceaa3d5SGerry Weißbach    private $LN = array(); // hold native names
20af1904f9SAndreas Gohr
21af1904f9SAndreas Gohr    /**
22af1904f9SAndreas Gohr     * Initialize
23af1904f9SAndreas Gohr     */
24488e4722SAndreas Gohr    function __construct() {
257c54a0a6SAndreas Gohr        global $conf;
26af1904f9SAndreas Gohr        require_once(DOKU_INC . 'inc/pageutils.php');
27af1904f9SAndreas Gohr        require_once(DOKU_INC . 'inc/utf8.php');
28af1904f9SAndreas Gohr
29af1904f9SAndreas Gohr        // load wanted translation into array
305e1f71acSGuillaume Turri        $this->translations = strtolower(str_replace(',', ' ', $this->getConf('translations')));
315e1f71acSGuillaume Turri        $this->translations = array_unique(array_filter(explode(' ', $this->translations)));
325e1f71acSGuillaume Turri        sort($this->translations);
337c54a0a6SAndreas Gohr
3449a71a89SAndreas Gohr        // load language names
3549a71a89SAndreas Gohr        $this->LN = confToHash(dirname(__FILE__) . '/lang/langnames.txt');
3649a71a89SAndreas Gohr
3704971eeaSAndreas Gohr        // display options
3804971eeaSAndreas Gohr        $this->opts = $this->getConf('display');
3904971eeaSAndreas Gohr        $this->opts = explode(',', $this->opts);
4004971eeaSAndreas Gohr        $this->opts = array_map('trim', $this->opts);
4104971eeaSAndreas Gohr        $this->opts = array_fill_keys($this->opts, true);
4204971eeaSAndreas Gohr
437c54a0a6SAndreas Gohr        // get default translation
440f9d57e2SGerry Weißbach        if(empty($conf['lang_before_translation'])) {
457c54a0a6SAndreas Gohr            $dfl = $conf['lang'];
467c54a0a6SAndreas Gohr        } else {
477c54a0a6SAndreas Gohr            $dfl = $conf['lang_before_translation'];
487c54a0a6SAndreas Gohr        }
495e1f71acSGuillaume Turri        if(in_array($dfl, $this->translations)) {
507c54a0a6SAndreas Gohr            $this->defaultlang = $dfl;
517c54a0a6SAndreas Gohr        } else {
527c54a0a6SAndreas Gohr            $this->defaultlang = '';
535e1f71acSGuillaume Turri            array_unshift($this->translations, '');
547c54a0a6SAndreas Gohr        }
557c54a0a6SAndreas Gohr
564e6ef383SGerry Weißbach        $this->translationsNs = $this->setupTNS();
57a4491becSGerry Weißbach        $JSINFO['conf']['lang'] = $dfl;
58a4491becSGerry Weißbach    }
59a4491becSGerry Weißbach
60a4491becSGerry Weißbach    /**
61a4491becSGerry Weißbach     * Find the current translation namespace
62a4491becSGerry Weißbach     * This may be detected automatically or defined by the config option
63a4491becSGerry Weißbach     **/
64*8ab22979Si-net /// software    function setupTNS($ID="", $forceAutotranslation=false) {
65a4491becSGerry Weißbach        global $conf;
66a4491becSGerry Weißbach
674e6ef383SGerry Weißbach        if ( !empty( $this->translationsNs) ) { return $this->translationsNs; }
68a4491becSGerry Weißbach        if ( empty($ID) ) { $ID = getID(); }
69a4491becSGerry Weißbach
70a4491becSGerry Weißbach        // autodetect?
71a4491becSGerry Weißbach        // this will only work for namespaces other than the root and default language
72*8ab22979Si-net /// software        if ( $forceAutotranslation || $this->getConf('autodetectnamespace') )
73a4491becSGerry Weißbach        {
74a4491becSGerry Weißbach            $lang = explode(':', $ID);
75a4491becSGerry Weißbach            foreach( array_reverse($lang) as $tns )
76a4491becSGerry Weißbach            {
77a4491becSGerry Weißbach                array_pop($lang);
784e6ef383SGerry Weißbach                if ( in_array($tns, $this->translations) )
79a4491becSGerry Weißbach                {
80a4491becSGerry Weißbach                    // Found
81a4491becSGerry Weißbach                    $tns = implode(":", $lang) . ':';
82a4491becSGerry Weißbach                    if($tns == ':' ) { $tns = ''; }
83a4491becSGerry Weißbach                    return $tns;
84a4491becSGerry Weißbach                }
85a4491becSGerry Weißbach            }
86a4491becSGerry Weißbach        }
87a4491becSGerry Weißbach
88a4491becSGerry Weißbach        // Array of translations can be givven
89a4491becSGerry Weißbach        $tnsA = explode(' ', $this->getConf('translationns'));
90a4491becSGerry Weißbach        if ( empty($tnsA) ) return ''; // there is just this one - and translation is active.
91a4491becSGerry Weißbach
92a4491becSGerry Weißbach        usort($tnsA,array($this, 'lensort') );
93a4491becSGerry Weißbach        foreach ( $tnsA as $tns ) {
94a4491becSGerry Weißbach            $tns = cleanID(trim($tns));
95a4491becSGerry Weißbach            if($tns && substr($tns, -1) != ':') { $tns .= ':'; }
96a4491becSGerry Weißbach            if($tns && strpos($ID,$tns) === false) continue;
97a4491becSGerry Weißbach            if($tns == ':' ) { $tns = ''; }
98a4491becSGerry Weißbach
99a4491becSGerry Weißbach            return $tns;
100a4491becSGerry Weißbach        }
101a4491becSGerry Weißbach
102a4491becSGerry Weißbach        return false;
103a4491becSGerry Weißbach    }
104a4491becSGerry Weißbach
105a4491becSGerry Weißbach    // Inner function for sorting
106a4491becSGerry Weißbach    private function lensort($a,$b){
107a4491becSGerry Weißbach        return strlen($b)-strlen($a);
108af1904f9SAndreas Gohr    }
109af1904f9SAndreas Gohr
110af1904f9SAndreas Gohr    /**
111af1904f9SAndreas Gohr     * Check if the given ID is a translation and return the language code.
112af1904f9SAndreas Gohr     */
113af1904f9SAndreas Gohr    function getLangPart($id) {
11426522e09SAndreas Gohr        list($lng) = $this->getTransParts($id);
11526522e09SAndreas Gohr        return $lng;
116af1904f9SAndreas Gohr    }
11726522e09SAndreas Gohr
11826522e09SAndreas Gohr    /**
119a4491becSGerry Weißbach     * Check if the given ID is a translation and return the ID up the translation root.
120a4491becSGerry Weißbach     */
121a4491becSGerry Weißbach    function getIDPart($id) {
122a4491becSGerry Weißbach        list($lng, $idpart) = $this->getTransParts($id);
123a4491becSGerry Weißbach        return $idpart;
124a4491becSGerry Weißbach    }
125a4491becSGerry Weißbach
126a4491becSGerry Weißbach    /**
12726522e09SAndreas Gohr     * Check if the given ID is a translation and return the language code and
12826522e09SAndreas Gohr     * the id part.
12926522e09SAndreas Gohr     */
13026522e09SAndreas Gohr    function getTransParts($id) {
1314e6ef383SGerry Weißbach        $rx = '/^' . $this->translationsNs . '(' . join('|', $this->translations) . '):(.*)/';
13226522e09SAndreas Gohr        if(preg_match($rx, $id, $match)) {
13326522e09SAndreas Gohr            return array($match[1], $match[2]);
13426522e09SAndreas Gohr        }
13526522e09SAndreas Gohr        return array('', $id);
136af1904f9SAndreas Gohr    }
137af1904f9SAndreas Gohr
138af1904f9SAndreas Gohr    /**
1397053cd66SAndreas Gohr     * Returns the browser language if it matches with one of the configured
1407053cd66SAndreas Gohr     * languages
1417053cd66SAndreas Gohr     */
1427053cd66SAndreas Gohr    function getBrowserLang() {
1435e1f71acSGuillaume Turri        $rx = '/(^|,|:|;|-)(' . join('|', $this->translations) . ')($|,|:|;|-)/i';
1447053cd66SAndreas Gohr        if(preg_match($rx, $_SERVER['HTTP_ACCEPT_LANGUAGE'], $match)) {
1457053cd66SAndreas Gohr            return strtolower($match[2]);
1467053cd66SAndreas Gohr        }
1477053cd66SAndreas Gohr        return false;
1487053cd66SAndreas Gohr    }
1497053cd66SAndreas Gohr
1507053cd66SAndreas Gohr    /**
1517c54a0a6SAndreas Gohr     * Returns the ID and name to the wanted translation, empty
1527c54a0a6SAndreas Gohr     * $lng is default lang
153af1904f9SAndreas Gohr     */
154af1904f9SAndreas Gohr    function buildTransID($lng, $idpart) {
155af1904f9SAndreas Gohr        global $conf;
156af1904f9SAndreas Gohr        if($lng) {
1574e6ef383SGerry Weißbach            $link = ':' . $this->translationsNs . $lng . ':' . $idpart;
158af1904f9SAndreas Gohr            $name = $lng;
159af1904f9SAndreas Gohr        } else {
1604e6ef383SGerry Weißbach            $link = ':' . $this->translationsNs . $idpart;
16104971eeaSAndreas Gohr            $name = $this->realLC('');
162af1904f9SAndreas Gohr        }
163af1904f9SAndreas Gohr        return array($link, $name);
164af1904f9SAndreas Gohr    }
165af1904f9SAndreas Gohr
1661469199dSAndreas Gohr    /**
16704971eeaSAndreas Gohr     * Returns the real language code, even when an empty one is given
16804971eeaSAndreas Gohr     * (eg. resolves th default language)
16904971eeaSAndreas Gohr     */
17004971eeaSAndreas Gohr    function realLC($lc) {
17104971eeaSAndreas Gohr        global $conf;
17204971eeaSAndreas Gohr        if($lc) {
17304971eeaSAndreas Gohr            return $lc;
1740f9d57e2SGerry Weißbach        } elseif(empty($conf['lang_before_translation'])) {
17504971eeaSAndreas Gohr            return $conf['lang'];
17604971eeaSAndreas Gohr        } else {
17704971eeaSAndreas Gohr            return $conf['lang_before_translation'];
17804971eeaSAndreas Gohr        }
17904971eeaSAndreas Gohr    }
18004971eeaSAndreas Gohr
18104971eeaSAndreas Gohr    /**
18284877e9bSAndreas Gohr     * Check if current ID should be translated and any GUI
18384877e9bSAndreas Gohr     * should be shown
18484877e9bSAndreas Gohr     */
18584877e9bSAndreas Gohr    function istranslatable($id, $checkact = true) {
18684877e9bSAndreas Gohr        global $ACT;
18784877e9bSAndreas Gohr
188e5aa1ca2SGerry Weißbach        if(auth_isAdmin()) return true;
189e5aa1ca2SGerry Weißbach
19084877e9bSAndreas Gohr        if($checkact && $ACT != 'show') return false;
1914e6ef383SGerry Weißbach        if($this->translationsNs && strpos($id, $this->translationsNs) !== 0) return false;
19284877e9bSAndreas Gohr        $skiptrans = trim($this->getConf('skiptrans'));
19384877e9bSAndreas Gohr        if($skiptrans && preg_match('/' . $skiptrans . '/ui', ':' . $id)) return false;
19484877e9bSAndreas Gohr        $meta = p_get_metadata($id);
19525fca7bdSGerry Weißbach        if(!empty($meta['plugin']['autotranslation']['notrans'])) return false;
19684877e9bSAndreas Gohr
19784877e9bSAndreas Gohr        return true;
19884877e9bSAndreas Gohr    }
19984877e9bSAndreas Gohr
20001dd7da9SAndreas Gohr    /**
20101dd7da9SAndreas Gohr     * Return the (localized) about link
20201dd7da9SAndreas Gohr     */
20301dd7da9SAndreas Gohr    function showAbout() {
204c9640767STomasz Tomasik        global $ID;
205c9640767STomasz Tomasik        global $conf;
206c9640767STomasz Tomasik        global $INFO;
207c9640767STomasz Tomasik
2085ad1c278SAndreas Gohr        $curlc = $this->getLangPart($ID);
209f34c9eb2SAndreas Gohr
210d0bdb959SAndreas Gohr        $about = $this->getConf('about');
211d0bdb959SAndreas Gohr        if($this->getConf('localabout')) {
212d0bdb959SAndreas Gohr            list($lc, $idpart) = $this->getTransParts($about);
213f34c9eb2SAndreas Gohr            list($about, $name) = $this->buildTransID($curlc, $idpart);
214d0bdb959SAndreas Gohr            $about = cleanID($about);
215d0bdb959SAndreas Gohr        }
216c9640767STomasz Tomasik
217c9640767STomasz Tomasik        $out = '';
218c9640767STomasz Tomasik        $out .= '<sup>';
219d0bdb959SAndreas Gohr        $out .= html_wikilink($about, '?');
220c9640767STomasz Tomasik        $out .= '</sup>';
221c9640767STomasz Tomasik
222c9640767STomasz Tomasik        return $out;
223c9640767STomasz Tomasik    }
224c9640767STomasz Tomasik
22584877e9bSAndreas Gohr    /**
226bbe70520SAndreas Gohr     * Returns a list of (lc => link) for all existing translations of a page
227bbe70520SAndreas Gohr     *
228bbe70520SAndreas Gohr     * @param $id
229bbe70520SAndreas Gohr     * @return array
230bbe70520SAndreas Gohr     */
231bbe70520SAndreas Gohr    function getAvailableTranslations($id) {
232bbe70520SAndreas Gohr        $result = array();
233bbe70520SAndreas Gohr
234bbe70520SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($id);
235bbe70520SAndreas Gohr        $lang = $this->realLC($lc);
236bbe70520SAndreas Gohr
2375e1f71acSGuillaume Turri        foreach($this->translations as $t) {
238bbe70520SAndreas Gohr            if($t == $lc) continue; //skip self
239bbe70520SAndreas Gohr            list($link, $name) = $this->buildTransID($t, $idpart);
240bbe70520SAndreas Gohr            if(page_exists($link)) {
241bbe70520SAndreas Gohr                $result[$name] = $link;
242bbe70520SAndreas Gohr            }
243bbe70520SAndreas Gohr        }
244bbe70520SAndreas Gohr
245bbe70520SAndreas Gohr        return $result;
246bbe70520SAndreas Gohr    }
247bbe70520SAndreas Gohr
248bbe70520SAndreas Gohr    /**
249649de279SAndreas Gohr     * Creates an UI for linking to the available and configured translations
250649de279SAndreas Gohr     *
251649de279SAndreas Gohr     * Can be called from the template or via the ~~TRANS~~ syntax component.
2521469199dSAndreas Gohr     */
253649de279SAndreas Gohr    public function showTranslations() {
2541469199dSAndreas Gohr        global $conf;
2551469199dSAndreas Gohr        global $INFO;
2561469199dSAndreas Gohr
257649de279SAndreas Gohr        if(!$this->istranslatable($INFO['id'])) return '';
25884877e9bSAndreas Gohr        $this->checkage();
2591469199dSAndreas Gohr
260649de279SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($INFO['id']);
26104971eeaSAndreas Gohr        $lang = $this->realLC($lc);
26239ecab8bSAndreas Gohr
26325fca7bdSGerry Weißbach        $out = '<div class="plugin_autotranslation">';
264c9640767STomasz Tomasik
26504971eeaSAndreas Gohr        //show title and about
266c730e7ddSAndreas Gohr        if(isset($this->opts['title'])) {
2671469199dSAndreas Gohr            $out .= '<span>' . $this->getLang('translations');
2688bd452a3SAndreas Gohr            if($this->getConf('about')) $out .= $this->showAbout();
2691469199dSAndreas Gohr            $out .= ':</span> ';
270c730e7ddSAndreas Gohr            if(isset($this->opts['twolines'])) $out .= '<br />';
271c9640767STomasz Tomasik        }
2721469199dSAndreas Gohr
27304971eeaSAndreas Gohr        // open wrapper
27404971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
27504971eeaSAndreas Gohr            // select needs its own styling
2761469199dSAndreas Gohr            if($INFO['exists']) {
2771469199dSAndreas Gohr                $class = 'wikilink1';
2781469199dSAndreas Gohr            } else {
2791469199dSAndreas Gohr                $class = 'wikilink2';
2801469199dSAndreas Gohr            }
28104971eeaSAndreas Gohr            if(isset($this->opts['flag'])) {
28204971eeaSAndreas Gohr                $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
283649de279SAndreas Gohr            }else{
284649de279SAndreas Gohr                $flag = '';
285c9640767STomasz Tomasik            }
286649de279SAndreas Gohr
287fbc6382cSAndreas Gohr            if($conf['userewrite']) {
288fbc6382cSAndreas Gohr                $action = wl();
289fbc6382cSAndreas Gohr            } else {
290fbc6382cSAndreas Gohr                $action = script();
291fbc6382cSAndreas Gohr            }
292fbc6382cSAndreas Gohr
293fbc6382cSAndreas Gohr            $out .= '<form action="' . $action . '" id="translation__dropdown">';
29404971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" class="' . $class . '" /> ';
295c9640767STomasz Tomasik            $out .= '<select name="id" class="' . $class . '">';
29604971eeaSAndreas Gohr        } else {
29704971eeaSAndreas Gohr            $out .= '<ul>';
29804971eeaSAndreas Gohr        }
29904971eeaSAndreas Gohr
30004971eeaSAndreas Gohr        // insert items
3015e1f71acSGuillaume Turri        foreach($this->translations as $t) {
30204971eeaSAndreas Gohr            $out .= $this->getTransItem($t, $idpart);
30304971eeaSAndreas Gohr        }
30404971eeaSAndreas Gohr
30504971eeaSAndreas Gohr        // close wrapper
30604971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
3071469199dSAndreas Gohr            $out .= '</select>';
3081469199dSAndreas Gohr            $out .= '<input name="go" type="submit" value="&rarr;" />';
3091469199dSAndreas Gohr            $out .= '</form>';
31004971eeaSAndreas Gohr        } else {
3111469199dSAndreas Gohr            $out .= '</ul>';
3121469199dSAndreas Gohr        }
3131469199dSAndreas Gohr
31404971eeaSAndreas Gohr        // show about if not already shown
315c730e7ddSAndreas Gohr        if(!isset($this->opts['title']) && $this->getConf('about')) {
31604971eeaSAndreas Gohr            $out .= '&nbsp';
31704971eeaSAndreas Gohr            $out .= $this->showAbout();
31804971eeaSAndreas Gohr        }
31904971eeaSAndreas Gohr
3201469199dSAndreas Gohr        $out .= '</div>';
3211469199dSAndreas Gohr
3221469199dSAndreas Gohr        return $out;
3231469199dSAndreas Gohr    }
324af1904f9SAndreas Gohr
32501dd7da9SAndreas Gohr    /**
326bbe70520SAndreas Gohr     * Return the local name
327bbe70520SAndreas Gohr     *
328bbe70520SAndreas Gohr     * @param $lang
329bbe70520SAndreas Gohr     * @return string
330bbe70520SAndreas Gohr     */
331bbe70520SAndreas Gohr    function getLocalName($lang) {
332bbe70520SAndreas Gohr        if($this->LN[$lang]) {
333bbe70520SAndreas Gohr            return $this->LN[$lang];
334bbe70520SAndreas Gohr        }
335bbe70520SAndreas Gohr        return $lang;
336bbe70520SAndreas Gohr    }
337bbe70520SAndreas Gohr
338bbe70520SAndreas Gohr    /**
33901dd7da9SAndreas Gohr     * Create the link or option for a single translation
34001dd7da9SAndreas Gohr     *
34104971eeaSAndreas Gohr     * @param $lc string      The language code
34201dd7da9SAndreas Gohr     * @param $idpart string  The ID of the translated page
34304971eeaSAndreas Gohr     * @returns string        The item
34401dd7da9SAndreas Gohr     */
34504971eeaSAndreas Gohr    function getTransItem($lc, $idpart) {
346c9640767STomasz Tomasik        global $ID;
347c9640767STomasz Tomasik        global $conf;
348c9640767STomasz Tomasik
34904971eeaSAndreas Gohr        list($link, $lang) = $this->buildTransID($lc, $idpart);
350c9640767STomasz Tomasik        $link = cleanID($link);
35104971eeaSAndreas Gohr
35204971eeaSAndreas Gohr        // class
353c9640767STomasz Tomasik        if(page_exists($link, '', false)) {
354c9640767STomasz Tomasik            $class = 'wikilink1';
355c9640767STomasz Tomasik        } else {
356c9640767STomasz Tomasik            $class = 'wikilink2';
357c9640767STomasz Tomasik        }
358c9640767STomasz Tomasik
35904971eeaSAndreas Gohr        // local language name
360bbe70520SAndreas Gohr        $localname = $this->getLocalName($lang);
361c9640767STomasz Tomasik
36204971eeaSAndreas Gohr        // current?
36304971eeaSAndreas Gohr        if($ID == $link) {
36404971eeaSAndreas Gohr            $sel = ' selected="selected"';
36504971eeaSAndreas Gohr            $class .= ' cur';
36604971eeaSAndreas Gohr        } else {
36704971eeaSAndreas Gohr            $sel = '';
36804971eeaSAndreas Gohr        }
369c9640767STomasz Tomasik
37004971eeaSAndreas Gohr        // flag
3710f9d57e2SGerry Weißbach        $flag = $style = '';
37204971eeaSAndreas Gohr        if(isset($this->opts['flag'])) {
37304971eeaSAndreas Gohr            $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
37404971eeaSAndreas Gohr            $style = ' style="background-image: url(\'' . $flag . '\')"';
37504971eeaSAndreas Gohr            $class .= ' flag';
37604971eeaSAndreas Gohr        }
37704971eeaSAndreas Gohr
37804971eeaSAndreas Gohr        // what to display as name
37904971eeaSAndreas Gohr        if(isset($this->opts['name'])) {
38004971eeaSAndreas Gohr            $display = hsc($localname);
381c730e7ddSAndreas Gohr            if(isset($this->opts['langcode'])) $display .= ' (' . hsc($lang) . ')';
382c730e7ddSAndreas Gohr        } elseif(isset($this->opts['langcode'])) {
38304971eeaSAndreas Gohr            $display = hsc($lang);
38404971eeaSAndreas Gohr        } else {
38504971eeaSAndreas Gohr            $display = '&nbsp;';
38604971eeaSAndreas Gohr        }
38704971eeaSAndreas Gohr
38804971eeaSAndreas Gohr        // prepare output
38904971eeaSAndreas Gohr        $out = '';
39004971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
3912546b043SAndreas Gohr            if($conf['useslash']) $link = str_replace(':', '/', $link);
3922546b043SAndreas Gohr
39304971eeaSAndreas Gohr            $out .= '<option class="' . $class . '" title="' . hsc($localname) . '" value="' . $link . '"' . $sel . $style . '>';
39404971eeaSAndreas Gohr            $out .= $display;
39504971eeaSAndreas Gohr            $out .= '</option>';
39604971eeaSAndreas Gohr        } else {
397c9640767STomasz Tomasik            $out .= '<li><div class="li">';
398a4491becSGerry Weißbach            $out .= '<a href="' . wl($link, 'tns') . '" class="' . $class . '" title="' . hsc($localname) . '">';
39904971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" />';
40004971eeaSAndreas Gohr            $out .= $display;
401c9640767STomasz Tomasik            $out .= '</a>';
402c9640767STomasz Tomasik            $out .= '</div></li>';
403c9640767STomasz Tomasik        }
404c9640767STomasz Tomasik
405c9640767STomasz Tomasik        return $out;
406c9640767STomasz Tomasik    }
407c9640767STomasz Tomasik
40884877e9bSAndreas Gohr    /**
40984877e9bSAndreas Gohr     * Checks if the current page is a translation of a page
41084877e9bSAndreas Gohr     * in the default language. Displays a notice when it is
411eb6de668SMichael Große     * older than the original page. Tries to link to a diff
41284877e9bSAndreas Gohr     * with changes on the original since the translation
41384877e9bSAndreas Gohr     */
41484877e9bSAndreas Gohr    function checkage() {
41584877e9bSAndreas Gohr        global $ID;
41684877e9bSAndreas Gohr        global $INFO;
41784877e9bSAndreas Gohr        if(!$this->getConf('checkage')) return;
41884877e9bSAndreas Gohr        if(!$INFO['exists']) return;
41984877e9bSAndreas Gohr        $lng = $this->getLangPart($ID);
42084877e9bSAndreas Gohr        if($lng == $this->defaultlang) return;
421af1904f9SAndreas Gohr
4224e6ef383SGerry Weißbach        $rx = '/^' . $this->translationsNs . '((' . join('|', $this->translations) . '):)?/';
42384877e9bSAndreas Gohr        $idpart = preg_replace($rx, '', $ID);
42484877e9bSAndreas Gohr
42584877e9bSAndreas Gohr        // compare modification times
42684877e9bSAndreas Gohr        list($orig, $name) = $this->buildTransID($this->defaultlang, $idpart);
42784877e9bSAndreas Gohr        $origfn = wikiFN($orig);
42884877e9bSAndreas Gohr        if($INFO['lastmod'] >= @filemtime($origfn)) return;
42984877e9bSAndreas Gohr
43084877e9bSAndreas Gohr        // get revision from before translation
43184877e9bSAndreas Gohr        $orev = 0;
432cde89045SAndreas Gohr        $changelog = new PageChangelog($orig);
433cde89045SAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
43484877e9bSAndreas Gohr        foreach($revs as $rev) {
43584877e9bSAndreas Gohr            if($rev < $INFO['lastmod']) {
43684877e9bSAndreas Gohr                $orev = $rev;
43784877e9bSAndreas Gohr                break;
43884877e9bSAndreas Gohr            }
43984877e9bSAndreas Gohr        }
44084877e9bSAndreas Gohr
44144552920SAndreas Gohr        // see if the found revision still exists
44244552920SAndreas Gohr        if($orev && !page_exists($orig, $orev)) $orev = 0;
44344552920SAndreas Gohr
44484877e9bSAndreas Gohr        // build the message and display it
445dc3fbdb9SOleksiy Zagorskyi        $orig = cleanID($orig);
44684877e9bSAndreas Gohr        $msg = sprintf($this->getLang('outdated'), wl($orig));
447eb6de668SMichael Große
448eb6de668SMichael Große        $difflink = $this->getOldDiffLink($orig, $INFO['lastmod']);
449eb6de668SMichael Große        if ($difflink) {
450eb6de668SMichael Große            $msg .= sprintf(' ' . $this->getLang('diff'), $difflink);
45184877e9bSAndreas Gohr        }
45200431e1eSAndreas Gohr
45300431e1eSAndreas Gohr        echo '<div class="notify">' . $msg . '</div>';
45484877e9bSAndreas Gohr    }
455a4491becSGerry Weißbach
456eb6de668SMichael Große    function getOldDiffLink($id, $lastmod) {
457eb6de668SMichael Große        // get revision from before translation
458eb6de668SMichael Große        $orev = false;
459d530d9deSAndreas Gohr        $changelog = new PageChangelog($id);
460d530d9deSAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
461eb6de668SMichael Große        foreach($revs as $rev) {
462eb6de668SMichael Große            if($rev < $lastmod) {
463eb6de668SMichael Große                $orev = $rev;
464eb6de668SMichael Große                break;
465eb6de668SMichael Große            }
466eb6de668SMichael Große        }
467eb6de668SMichael Große        if($orev && !page_exists($id, $orev)) {
468eb6de668SMichael Große            return false;
469eb6de668SMichael Große        }
470eb6de668SMichael Große        $id = cleanID($id);
471eb6de668SMichael Große        return wl($id, array('do' => 'diff', 'rev' => $orev));
472eb6de668SMichael Große
473eb6de668SMichael Große    }
474e33449a8SGerry Weißbach
475a4491becSGerry Weißbach    /**
476a4491becSGerry Weißbach     * Checks if the current ID has a translated page
477a4491becSGerry Weißbach     */
478a4491becSGerry Weißbach    function hasTranslation($inputID = null) {
479a4491becSGerry Weißbach        global $ID, $INFO, $conf;
480a4491becSGerry Weißbach
481a4491becSGerry Weißbach        if ( empty($inputID) )
482a4491becSGerry Weißbach        {
483a4491becSGerry Weißbach            $inputID = $ID;
484a4491becSGerry Weißbach        }
485a4491becSGerry Weißbach
486a4491becSGerry Weißbach        if ( !$this->istranslatable($id) ) return false;
487a4491becSGerry Weißbach
488a4491becSGerry Weißbach        $idpart = $this->getIDPart($inputID);
489a4491becSGerry Weißbach
4904e6ef383SGerry Weißbach        foreach($this->translations as $t)
491a4491becSGerry Weißbach        {
492a4491becSGerry Weißbach            list($link,$name) = $this->buildTransID($t,$idpart,false);
493a4491becSGerry Weißbach            $link = cleanID($link);
494a4491becSGerry Weißbach
495a4491becSGerry Weißbach            if( $inputID != $link && page_exists($link,'',false) ){
496a4491becSGerry Weißbach                return true;
497a4491becSGerry Weißbach            }
498a4491becSGerry Weißbach        }
499a4491becSGerry Weißbach
500a4491becSGerry Weißbach        return false;
501a4491becSGerry Weißbach    }
502af1904f9SAndreas Gohr}
503