xref: /plugin/autotranslation/helper.php (revision e35b83548c7cf6e2a870ac00d7b168b0672d8609)
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() {
25b0afc21cSGerry Weißbach        global $conf, $JSINFO;
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     **/
648ab22979Si-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
728ab22979Si-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() {
143b0afc21cSGerry Weißbach        if(empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
144b0afc21cSGerry Weißbach            return false;
145b0afc21cSGerry Weißbach        }
1465e1f71acSGuillaume Turri        $rx = '/(^|,|:|;|-)(' . join('|', $this->translations) . ')($|,|:|;|-)/i';
1477053cd66SAndreas Gohr        if(preg_match($rx, $_SERVER['HTTP_ACCEPT_LANGUAGE'], $match)) {
1487053cd66SAndreas Gohr            return strtolower($match[2]);
1497053cd66SAndreas Gohr        }
1507053cd66SAndreas Gohr        return false;
1517053cd66SAndreas Gohr    }
1527053cd66SAndreas Gohr
1537053cd66SAndreas Gohr    /**
1547c54a0a6SAndreas Gohr     * Returns the ID and name to the wanted translation, empty
1557c54a0a6SAndreas Gohr     * $lng is default lang
156af1904f9SAndreas Gohr     */
157af1904f9SAndreas Gohr    function buildTransID($lng, $idpart) {
158af1904f9SAndreas Gohr        global $conf;
159af1904f9SAndreas Gohr        if($lng) {
1604e6ef383SGerry Weißbach            $link = ':' . $this->translationsNs . $lng . ':' . $idpart;
161af1904f9SAndreas Gohr            $name = $lng;
162af1904f9SAndreas Gohr        } else {
1634e6ef383SGerry Weißbach            $link = ':' . $this->translationsNs . $idpart;
16404971eeaSAndreas Gohr            $name = $this->realLC('');
165af1904f9SAndreas Gohr        }
166af1904f9SAndreas Gohr        return array($link, $name);
167af1904f9SAndreas Gohr    }
168af1904f9SAndreas Gohr
1691469199dSAndreas Gohr    /**
17004971eeaSAndreas Gohr     * Returns the real language code, even when an empty one is given
17104971eeaSAndreas Gohr     * (eg. resolves th default language)
17204971eeaSAndreas Gohr     */
17304971eeaSAndreas Gohr    function realLC($lc) {
17404971eeaSAndreas Gohr        global $conf;
17504971eeaSAndreas Gohr        if($lc) {
17604971eeaSAndreas Gohr            return $lc;
1770f9d57e2SGerry Weißbach        } elseif(empty($conf['lang_before_translation'])) {
17804971eeaSAndreas Gohr            return $conf['lang'];
17904971eeaSAndreas Gohr        } else {
18004971eeaSAndreas Gohr            return $conf['lang_before_translation'];
18104971eeaSAndreas Gohr        }
18204971eeaSAndreas Gohr    }
18304971eeaSAndreas Gohr
18404971eeaSAndreas Gohr    /**
18584877e9bSAndreas Gohr     * Check if current ID should be translated and any GUI
18684877e9bSAndreas Gohr     * should be shown
18784877e9bSAndreas Gohr     */
18884877e9bSAndreas Gohr    function istranslatable($id, $checkact = true) {
18984877e9bSAndreas Gohr        global $ACT;
19084877e9bSAndreas Gohr
191e5aa1ca2SGerry Weißbach        if(auth_isAdmin()) return true;
192e5aa1ca2SGerry Weißbach
19384877e9bSAndreas Gohr        if($checkact && $ACT != 'show') return false;
1944e6ef383SGerry Weißbach        if($this->translationsNs && strpos($id, $this->translationsNs) !== 0) return false;
19584877e9bSAndreas Gohr        $skiptrans = trim($this->getConf('skiptrans'));
19684877e9bSAndreas Gohr        if($skiptrans && preg_match('/' . $skiptrans . '/ui', ':' . $id)) return false;
19784877e9bSAndreas Gohr        $meta = p_get_metadata($id);
19825fca7bdSGerry Weißbach        if(!empty($meta['plugin']['autotranslation']['notrans'])) return false;
19984877e9bSAndreas Gohr
20084877e9bSAndreas Gohr        return true;
20184877e9bSAndreas Gohr    }
20284877e9bSAndreas Gohr
20301dd7da9SAndreas Gohr    /**
20401dd7da9SAndreas Gohr     * Return the (localized) about link
20501dd7da9SAndreas Gohr     */
20601dd7da9SAndreas Gohr    function showAbout() {
207c9640767STomasz Tomasik        global $ID;
208c9640767STomasz Tomasik        global $conf;
209c9640767STomasz Tomasik        global $INFO;
210c9640767STomasz Tomasik
2115ad1c278SAndreas Gohr        $curlc = $this->getLangPart($ID);
212f34c9eb2SAndreas Gohr
213d0bdb959SAndreas Gohr        $about = $this->getConf('about');
214d0bdb959SAndreas Gohr        if($this->getConf('localabout')) {
215d0bdb959SAndreas Gohr            list($lc, $idpart) = $this->getTransParts($about);
216f34c9eb2SAndreas Gohr            list($about, $name) = $this->buildTransID($curlc, $idpart);
217d0bdb959SAndreas Gohr            $about = cleanID($about);
218d0bdb959SAndreas Gohr        }
219c9640767STomasz Tomasik
220c9640767STomasz Tomasik        $out = '';
221c9640767STomasz Tomasik        $out .= '<sup>';
222d0bdb959SAndreas Gohr        $out .= html_wikilink($about, '?');
223c9640767STomasz Tomasik        $out .= '</sup>';
224c9640767STomasz Tomasik
225c9640767STomasz Tomasik        return $out;
226c9640767STomasz Tomasik    }
227c9640767STomasz Tomasik
22884877e9bSAndreas Gohr    /**
229bbe70520SAndreas Gohr     * Returns a list of (lc => link) for all existing translations of a page
230bbe70520SAndreas Gohr     *
231bbe70520SAndreas Gohr     * @param $id
232bbe70520SAndreas Gohr     * @return array
233bbe70520SAndreas Gohr     */
234bbe70520SAndreas Gohr    function getAvailableTranslations($id) {
235bbe70520SAndreas Gohr        $result = array();
236bbe70520SAndreas Gohr
237bbe70520SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($id);
238bbe70520SAndreas Gohr        $lang = $this->realLC($lc);
239bbe70520SAndreas Gohr
2405e1f71acSGuillaume Turri        foreach($this->translations as $t) {
241bbe70520SAndreas Gohr            if($t == $lc) continue; //skip self
242bbe70520SAndreas Gohr            list($link, $name) = $this->buildTransID($t, $idpart);
243bbe70520SAndreas Gohr            if(page_exists($link)) {
244bbe70520SAndreas Gohr                $result[$name] = $link;
245bbe70520SAndreas Gohr            }
246bbe70520SAndreas Gohr        }
247bbe70520SAndreas Gohr
248bbe70520SAndreas Gohr        return $result;
249bbe70520SAndreas Gohr    }
250bbe70520SAndreas Gohr
251bbe70520SAndreas Gohr    /**
252649de279SAndreas Gohr     * Creates an UI for linking to the available and configured translations
253649de279SAndreas Gohr     *
254649de279SAndreas Gohr     * Can be called from the template or via the ~~TRANS~~ syntax component.
2551469199dSAndreas Gohr     */
256649de279SAndreas Gohr    public function showTranslations() {
2571469199dSAndreas Gohr        global $conf;
2581469199dSAndreas Gohr        global $INFO;
2591469199dSAndreas Gohr
260649de279SAndreas Gohr        if(!$this->istranslatable($INFO['id'])) return '';
26184877e9bSAndreas Gohr        $this->checkage();
2621469199dSAndreas Gohr
263649de279SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($INFO['id']);
26404971eeaSAndreas Gohr        $lang = $this->realLC($lc);
26539ecab8bSAndreas Gohr
26625fca7bdSGerry Weißbach        $out = '<div class="plugin_autotranslation">';
267c9640767STomasz Tomasik
26804971eeaSAndreas Gohr        //show title and about
269c730e7ddSAndreas Gohr        if(isset($this->opts['title'])) {
2701469199dSAndreas Gohr            $out .= '<span>' . $this->getLang('translations');
2718bd452a3SAndreas Gohr            if($this->getConf('about')) $out .= $this->showAbout();
2721469199dSAndreas Gohr            $out .= ':</span> ';
273c730e7ddSAndreas Gohr            if(isset($this->opts['twolines'])) $out .= '<br />';
274c9640767STomasz Tomasik        }
2751469199dSAndreas Gohr
27604971eeaSAndreas Gohr        // open wrapper
27704971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
27804971eeaSAndreas Gohr            // select needs its own styling
2791469199dSAndreas Gohr            if($INFO['exists']) {
2801469199dSAndreas Gohr                $class = 'wikilink1';
2811469199dSAndreas Gohr            } else {
2821469199dSAndreas Gohr                $class = 'wikilink2';
2831469199dSAndreas Gohr            }
28404971eeaSAndreas Gohr            if(isset($this->opts['flag'])) {
28504971eeaSAndreas Gohr                $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
286649de279SAndreas Gohr            }else{
287649de279SAndreas Gohr                $flag = '';
288c9640767STomasz Tomasik            }
289649de279SAndreas Gohr
290fbc6382cSAndreas Gohr            if($conf['userewrite']) {
291fbc6382cSAndreas Gohr                $action = wl();
292fbc6382cSAndreas Gohr            } else {
293fbc6382cSAndreas Gohr                $action = script();
294fbc6382cSAndreas Gohr            }
295fbc6382cSAndreas Gohr
296fbc6382cSAndreas Gohr            $out .= '<form action="' . $action . '" id="translation__dropdown">';
29704971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" class="' . $class . '" /> ';
298c9640767STomasz Tomasik            $out .= '<select name="id" class="' . $class . '">';
29904971eeaSAndreas Gohr        } else {
30004971eeaSAndreas Gohr            $out .= '<ul>';
30104971eeaSAndreas Gohr        }
30204971eeaSAndreas Gohr
30304971eeaSAndreas Gohr        // insert items
3045e1f71acSGuillaume Turri        foreach($this->translations as $t) {
30504971eeaSAndreas Gohr            $out .= $this->getTransItem($t, $idpart);
30604971eeaSAndreas Gohr        }
30704971eeaSAndreas Gohr
30804971eeaSAndreas Gohr        // close wrapper
30904971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
3101469199dSAndreas Gohr            $out .= '</select>';
3111469199dSAndreas Gohr            $out .= '<input name="go" type="submit" value="&rarr;" />';
3121469199dSAndreas Gohr            $out .= '</form>';
31304971eeaSAndreas Gohr        } else {
3141469199dSAndreas Gohr            $out .= '</ul>';
3151469199dSAndreas Gohr        }
3161469199dSAndreas Gohr
31704971eeaSAndreas Gohr        // show about if not already shown
318c730e7ddSAndreas Gohr        if(!isset($this->opts['title']) && $this->getConf('about')) {
31904971eeaSAndreas Gohr            $out .= '&nbsp';
32004971eeaSAndreas Gohr            $out .= $this->showAbout();
32104971eeaSAndreas Gohr        }
32204971eeaSAndreas Gohr
3231469199dSAndreas Gohr        $out .= '</div>';
3241469199dSAndreas Gohr
3251469199dSAndreas Gohr        return $out;
3261469199dSAndreas Gohr    }
327af1904f9SAndreas Gohr
32801dd7da9SAndreas Gohr    /**
329bbe70520SAndreas Gohr     * Return the local name
330bbe70520SAndreas Gohr     *
331bbe70520SAndreas Gohr     * @param $lang
332bbe70520SAndreas Gohr     * @return string
333bbe70520SAndreas Gohr     */
334bbe70520SAndreas Gohr    function getLocalName($lang) {
335bbe70520SAndreas Gohr        if($this->LN[$lang]) {
336bbe70520SAndreas Gohr            return $this->LN[$lang];
337bbe70520SAndreas Gohr        }
338bbe70520SAndreas Gohr        return $lang;
339bbe70520SAndreas Gohr    }
340bbe70520SAndreas Gohr
341bbe70520SAndreas Gohr    /**
34201dd7da9SAndreas Gohr     * Create the link or option for a single translation
34301dd7da9SAndreas Gohr     *
34404971eeaSAndreas Gohr     * @param $lc string      The language code
34501dd7da9SAndreas Gohr     * @param $idpart string  The ID of the translated page
34604971eeaSAndreas Gohr     * @returns string        The item
34701dd7da9SAndreas Gohr     */
34804971eeaSAndreas Gohr    function getTransItem($lc, $idpart) {
349c9640767STomasz Tomasik        global $ID;
350c9640767STomasz Tomasik        global $conf;
351c9640767STomasz Tomasik
35204971eeaSAndreas Gohr        list($link, $lang) = $this->buildTransID($lc, $idpart);
353c9640767STomasz Tomasik        $link = cleanID($link);
35404971eeaSAndreas Gohr
35504971eeaSAndreas Gohr        // class
356c9640767STomasz Tomasik        if(page_exists($link, '', false)) {
357c9640767STomasz Tomasik            $class = 'wikilink1';
358c9640767STomasz Tomasik        } else {
359c9640767STomasz Tomasik            $class = 'wikilink2';
360c9640767STomasz Tomasik        }
361c9640767STomasz Tomasik
36204971eeaSAndreas Gohr        // local language name
363bbe70520SAndreas Gohr        $localname = $this->getLocalName($lang);
364c9640767STomasz Tomasik
36504971eeaSAndreas Gohr        // current?
36604971eeaSAndreas Gohr        if($ID == $link) {
36704971eeaSAndreas Gohr            $sel = ' selected="selected"';
36804971eeaSAndreas Gohr            $class .= ' cur';
36904971eeaSAndreas Gohr        } else {
37004971eeaSAndreas Gohr            $sel = '';
37104971eeaSAndreas Gohr        }
372c9640767STomasz Tomasik
37304971eeaSAndreas Gohr        // flag
3740f9d57e2SGerry Weißbach        $flag = $style = '';
37504971eeaSAndreas Gohr        if(isset($this->opts['flag'])) {
37604971eeaSAndreas Gohr            $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
37704971eeaSAndreas Gohr            $style = ' style="background-image: url(\'' . $flag . '\')"';
37804971eeaSAndreas Gohr            $class .= ' flag';
37904971eeaSAndreas Gohr        }
38004971eeaSAndreas Gohr
38104971eeaSAndreas Gohr        // what to display as name
38204971eeaSAndreas Gohr        if(isset($this->opts['name'])) {
38304971eeaSAndreas Gohr            $display = hsc($localname);
384c730e7ddSAndreas Gohr            if(isset($this->opts['langcode'])) $display .= ' (' . hsc($lang) . ')';
385c730e7ddSAndreas Gohr        } elseif(isset($this->opts['langcode'])) {
38604971eeaSAndreas Gohr            $display = hsc($lang);
38704971eeaSAndreas Gohr        } else {
38804971eeaSAndreas Gohr            $display = '&nbsp;';
38904971eeaSAndreas Gohr        }
39004971eeaSAndreas Gohr
39104971eeaSAndreas Gohr        // prepare output
39204971eeaSAndreas Gohr        $out = '';
39304971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
3942546b043SAndreas Gohr            if($conf['useslash']) $link = str_replace(':', '/', $link);
3952546b043SAndreas Gohr
39604971eeaSAndreas Gohr            $out .= '<option class="' . $class . '" title="' . hsc($localname) . '" value="' . $link . '"' . $sel . $style . '>';
39704971eeaSAndreas Gohr            $out .= $display;
39804971eeaSAndreas Gohr            $out .= '</option>';
39904971eeaSAndreas Gohr        } else {
400c9640767STomasz Tomasik            $out .= '<li><div class="li">';
401a4491becSGerry Weißbach            $out .= '<a href="' . wl($link, 'tns') . '" class="' . $class . '" title="' . hsc($localname) . '">';
40204971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" />';
40304971eeaSAndreas Gohr            $out .= $display;
404c9640767STomasz Tomasik            $out .= '</a>';
405c9640767STomasz Tomasik            $out .= '</div></li>';
406c9640767STomasz Tomasik        }
407c9640767STomasz Tomasik
408c9640767STomasz Tomasik        return $out;
409c9640767STomasz Tomasik    }
410c9640767STomasz Tomasik
41184877e9bSAndreas Gohr    /**
41284877e9bSAndreas Gohr     * Checks if the current page is a translation of a page
41384877e9bSAndreas Gohr     * in the default language. Displays a notice when it is
414eb6de668SMichael Große     * older than the original page. Tries to link to a diff
41584877e9bSAndreas Gohr     * with changes on the original since the translation
41684877e9bSAndreas Gohr     */
41784877e9bSAndreas Gohr    function checkage() {
41884877e9bSAndreas Gohr        global $ID;
41984877e9bSAndreas Gohr        global $INFO;
42084877e9bSAndreas Gohr        if(!$this->getConf('checkage')) return;
42184877e9bSAndreas Gohr        if(!$INFO['exists']) return;
42284877e9bSAndreas Gohr        $lng = $this->getLangPart($ID);
42384877e9bSAndreas Gohr        if($lng == $this->defaultlang) return;
424af1904f9SAndreas Gohr
4254e6ef383SGerry Weißbach        $rx = '/^' . $this->translationsNs . '((' . join('|', $this->translations) . '):)?/';
42684877e9bSAndreas Gohr        $idpart = preg_replace($rx, '', $ID);
42784877e9bSAndreas Gohr
42884877e9bSAndreas Gohr        // compare modification times
42984877e9bSAndreas Gohr        list($orig, $name) = $this->buildTransID($this->defaultlang, $idpart);
43084877e9bSAndreas Gohr        $origfn = wikiFN($orig);
43184877e9bSAndreas Gohr        if($INFO['lastmod'] >= @filemtime($origfn)) return;
43284877e9bSAndreas Gohr
43384877e9bSAndreas Gohr        // get revision from before translation
43484877e9bSAndreas Gohr        $orev = 0;
435cde89045SAndreas Gohr        $changelog = new PageChangelog($orig);
436cde89045SAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
43784877e9bSAndreas Gohr        foreach($revs as $rev) {
43884877e9bSAndreas Gohr            if($rev < $INFO['lastmod']) {
43984877e9bSAndreas Gohr                $orev = $rev;
44084877e9bSAndreas Gohr                break;
44184877e9bSAndreas Gohr            }
44284877e9bSAndreas Gohr        }
44384877e9bSAndreas Gohr
44444552920SAndreas Gohr        // see if the found revision still exists
44544552920SAndreas Gohr        if($orev && !page_exists($orig, $orev)) $orev = 0;
44644552920SAndreas Gohr
44784877e9bSAndreas Gohr        // build the message and display it
448dc3fbdb9SOleksiy Zagorskyi        $orig = cleanID($orig);
44984877e9bSAndreas Gohr        $msg = sprintf($this->getLang('outdated'), wl($orig));
450eb6de668SMichael Große
451eb6de668SMichael Große        $difflink = $this->getOldDiffLink($orig, $INFO['lastmod']);
452eb6de668SMichael Große        if ($difflink) {
453eb6de668SMichael Große            $msg .= sprintf(' ' . $this->getLang('diff'), $difflink);
45484877e9bSAndreas Gohr        }
45500431e1eSAndreas Gohr
45600431e1eSAndreas Gohr        echo '<div class="notify">' . $msg . '</div>';
45784877e9bSAndreas Gohr    }
458a4491becSGerry Weißbach
459eb6de668SMichael Große    function getOldDiffLink($id, $lastmod) {
460eb6de668SMichael Große        // get revision from before translation
461eb6de668SMichael Große        $orev = false;
462d530d9deSAndreas Gohr        $changelog = new PageChangelog($id);
463d530d9deSAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
464eb6de668SMichael Große        foreach($revs as $rev) {
465eb6de668SMichael Große            if($rev < $lastmod) {
466eb6de668SMichael Große                $orev = $rev;
467eb6de668SMichael Große                break;
468eb6de668SMichael Große            }
469eb6de668SMichael Große        }
470eb6de668SMichael Große        if($orev && !page_exists($id, $orev)) {
471eb6de668SMichael Große            return false;
472eb6de668SMichael Große        }
473eb6de668SMichael Große        $id = cleanID($id);
474eb6de668SMichael Große        return wl($id, array('do' => 'diff', 'rev' => $orev));
475eb6de668SMichael Große
476eb6de668SMichael Große    }
477e33449a8SGerry Weißbach
478a4491becSGerry Weißbach    /**
479a4491becSGerry Weißbach     * Checks if the current ID has a translated page
480a4491becSGerry Weißbach     */
481a4491becSGerry Weißbach    function hasTranslation($inputID = null) {
482a4491becSGerry Weißbach        global $ID, $INFO, $conf;
483a4491becSGerry Weißbach
484*e35b8354SGerry Weißbach        if ( empty($inputID) ) {
485*e35b8354SGerry Weißbach            $inputID = (isset($ID) && $ID !== '') ? $ID : getID();
486*e35b8354SGerry Weißbach        }
487*e35b8354SGerry Weißbach        if ( $inputID === '' || $inputID === null ) {
488*e35b8354SGerry Weißbach            return false;
489a4491becSGerry Weißbach        }
490a4491becSGerry Weißbach
491*e35b8354SGerry Weißbach        if ( !$this->istranslatable($inputID) ) return false;
492a4491becSGerry Weißbach
493a4491becSGerry Weißbach        $idpart = $this->getIDPart($inputID);
494a4491becSGerry Weißbach
4954e6ef383SGerry Weißbach        foreach($this->translations as $t)
496a4491becSGerry Weißbach        {
497b0afc21cSGerry Weißbach            list($link,$name) = $this->buildTransID($t,$idpart);
498a4491becSGerry Weißbach            $link = cleanID($link);
499a4491becSGerry Weißbach
500a4491becSGerry Weißbach            if( $inputID != $link && page_exists($link,'',false) ){
501a4491becSGerry Weißbach                return true;
502a4491becSGerry Weißbach            }
503a4491becSGerry Weißbach        }
504a4491becSGerry Weißbach
505a4491becSGerry Weißbach        return false;
506a4491becSGerry Weißbach    }
507af1904f9SAndreas Gohr}
508