xref: /plugin/autotranslation/helper.php (revision e33449a85c8468e2e48c870680e1f12f14f1f59d)
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 {
135e1f71acSGuillaume Turri    var $translations = array();
145e1f71acSGuillaume Turri    var $translationNs = '';
157c54a0a6SAndreas Gohr    var $defaultlang = '';
1649a71a89SAndreas Gohr    var $LN = array(); // hold native names
1704971eeaSAndreas Gohr    var $opts = array(); // display options
18af1904f9SAndreas Gohr
19af1904f9SAndreas Gohr    /**
20af1904f9SAndreas Gohr     * Initialize
21af1904f9SAndreas Gohr     */
22488e4722SAndreas Gohr    function __construct() {
237c54a0a6SAndreas Gohr        global $conf;
24af1904f9SAndreas Gohr        require_once(DOKU_INC . 'inc/pageutils.php');
25af1904f9SAndreas Gohr        require_once(DOKU_INC . 'inc/utf8.php');
26af1904f9SAndreas Gohr
27af1904f9SAndreas Gohr        // load wanted translation into array
285e1f71acSGuillaume Turri        $this->translations = strtolower(str_replace(',', ' ', $this->getConf('translations')));
295e1f71acSGuillaume Turri        $this->translations = array_unique(array_filter(explode(' ', $this->translations)));
305e1f71acSGuillaume Turri        sort($this->translations);
317c54a0a6SAndreas Gohr
3249a71a89SAndreas Gohr        // load language names
3349a71a89SAndreas Gohr        $this->LN = confToHash(dirname(__FILE__) . '/lang/langnames.txt');
3449a71a89SAndreas Gohr
3504971eeaSAndreas Gohr        // display options
3604971eeaSAndreas Gohr        $this->opts = $this->getConf('display');
3704971eeaSAndreas Gohr        $this->opts = explode(',', $this->opts);
3804971eeaSAndreas Gohr        $this->opts = array_map('trim', $this->opts);
3904971eeaSAndreas Gohr        $this->opts = array_fill_keys($this->opts, true);
4004971eeaSAndreas Gohr
417c54a0a6SAndreas Gohr        // get default translation
420f9d57e2SGerry Weißbach        if(empty($conf['lang_before_translation'])) {
437c54a0a6SAndreas Gohr            $dfl = $conf['lang'];
447c54a0a6SAndreas Gohr        } else {
457c54a0a6SAndreas Gohr            $dfl = $conf['lang_before_translation'];
467c54a0a6SAndreas Gohr        }
475e1f71acSGuillaume Turri        if(in_array($dfl, $this->translations)) {
487c54a0a6SAndreas Gohr            $this->defaultlang = $dfl;
497c54a0a6SAndreas Gohr        } else {
507c54a0a6SAndreas Gohr            $this->defaultlang = '';
515e1f71acSGuillaume Turri            array_unshift($this->translations, '');
527c54a0a6SAndreas Gohr        }
537c54a0a6SAndreas Gohr
544e6ef383SGerry Weißbach        $this->translationsNs = $this->setupTNS();
55a4491becSGerry Weißbach        $JSINFO['conf']['lang'] = $dfl;
56a4491becSGerry Weißbach    }
57a4491becSGerry Weißbach
58a4491becSGerry Weißbach    /**
59a4491becSGerry Weißbach     * Find the current translation namespace
60a4491becSGerry Weißbach     * This may be detected automatically or defined by the config option
61a4491becSGerry Weißbach     **/
62a4491becSGerry Weißbach    function setupTNS($ID="") {
63a4491becSGerry Weißbach        global $conf;
64a4491becSGerry Weißbach
654e6ef383SGerry Weißbach        if ( !empty( $this->translationsNs) ) { return $this->translationsNs; }
66a4491becSGerry Weißbach        if ( empty($ID) ) { $ID = getID(); }
67a4491becSGerry Weißbach
68a4491becSGerry Weißbach        // autodetect?
69a4491becSGerry Weißbach        // this will only work for namespaces other than the root and default language
70a4491becSGerry Weißbach        if ( $this->getConf('autodetectnamespace') )
71a4491becSGerry Weißbach        {
72a4491becSGerry Weißbach            $lang = explode(':', $ID);
73a4491becSGerry Weißbach            foreach( array_reverse($lang) as $tns )
74a4491becSGerry Weißbach            {
75a4491becSGerry Weißbach                array_pop($lang);
764e6ef383SGerry Weißbach                if ( in_array($tns, $this->translations) )
77a4491becSGerry Weißbach                {
78a4491becSGerry Weißbach                    // Found
79a4491becSGerry Weißbach                    $tns = implode(":", $lang) . ':';
80a4491becSGerry Weißbach                    if($tns == ':' ) { $tns = ''; }
81a4491becSGerry Weißbach                    return $tns;
82a4491becSGerry Weißbach                }
83a4491becSGerry Weißbach            }
84a4491becSGerry Weißbach        }
85a4491becSGerry Weißbach
86a4491becSGerry Weißbach        // Array of translations can be givven
87a4491becSGerry Weißbach        $tnsA = explode(' ', $this->getConf('translationns'));
88a4491becSGerry Weißbach        if ( empty($tnsA) ) return ''; // there is just this one - and translation is active.
89a4491becSGerry Weißbach
90a4491becSGerry Weißbach        usort($tnsA,array($this, 'lensort') );
91a4491becSGerry Weißbach        foreach ( $tnsA as $tns ) {
92a4491becSGerry Weißbach            $tns = cleanID(trim($tns));
93a4491becSGerry Weißbach            if($tns && substr($tns, -1) != ':') { $tns .= ':'; }
94a4491becSGerry Weißbach            if($tns && strpos($ID,$tns) === false) continue;
95a4491becSGerry Weißbach            if($tns == ':' ) { $tns = ''; }
96a4491becSGerry Weißbach
97a4491becSGerry Weißbach            return $tns;
98a4491becSGerry Weißbach        }
99a4491becSGerry Weißbach
100a4491becSGerry Weißbach        return false;
101a4491becSGerry Weißbach    }
102a4491becSGerry Weißbach
103a4491becSGerry Weißbach    // Inner function for sorting
104a4491becSGerry Weißbach    private function lensort($a,$b){
105a4491becSGerry Weißbach        return strlen($b)-strlen($a);
106af1904f9SAndreas Gohr    }
107af1904f9SAndreas Gohr
108af1904f9SAndreas Gohr    /**
109af1904f9SAndreas Gohr     * Check if the given ID is a translation and return the language code.
110af1904f9SAndreas Gohr     */
111af1904f9SAndreas Gohr    function getLangPart($id) {
11226522e09SAndreas Gohr        list($lng) = $this->getTransParts($id);
11326522e09SAndreas Gohr        return $lng;
114af1904f9SAndreas Gohr    }
11526522e09SAndreas Gohr
11626522e09SAndreas Gohr    /**
117a4491becSGerry Weißbach     * Check if the given ID is a translation and return the ID up the translation root.
118a4491becSGerry Weißbach     */
119a4491becSGerry Weißbach    function getIDPart($id) {
120a4491becSGerry Weißbach        list($lng, $idpart) = $this->getTransParts($id);
121a4491becSGerry Weißbach        return $idpart;
122a4491becSGerry Weißbach    }
123a4491becSGerry Weißbach
124a4491becSGerry Weißbach    /**
12526522e09SAndreas Gohr     * Check if the given ID is a translation and return the language code and
12626522e09SAndreas Gohr     * the id part.
12726522e09SAndreas Gohr     */
12826522e09SAndreas Gohr    function getTransParts($id) {
1294e6ef383SGerry Weißbach        $rx = '/^' . $this->translationsNs . '(' . join('|', $this->translations) . '):(.*)/';
13026522e09SAndreas Gohr        if(preg_match($rx, $id, $match)) {
13126522e09SAndreas Gohr            return array($match[1], $match[2]);
13226522e09SAndreas Gohr        }
13326522e09SAndreas Gohr        return array('', $id);
134af1904f9SAndreas Gohr    }
135af1904f9SAndreas Gohr
136af1904f9SAndreas Gohr    /**
1377053cd66SAndreas Gohr     * Returns the browser language if it matches with one of the configured
1387053cd66SAndreas Gohr     * languages
1397053cd66SAndreas Gohr     */
1407053cd66SAndreas Gohr    function getBrowserLang() {
1415e1f71acSGuillaume Turri        $rx = '/(^|,|:|;|-)(' . join('|', $this->translations) . ')($|,|:|;|-)/i';
1427053cd66SAndreas Gohr        if(preg_match($rx, $_SERVER['HTTP_ACCEPT_LANGUAGE'], $match)) {
1437053cd66SAndreas Gohr            return strtolower($match[2]);
1447053cd66SAndreas Gohr        }
1457053cd66SAndreas Gohr        return false;
1467053cd66SAndreas Gohr    }
1477053cd66SAndreas Gohr
1487053cd66SAndreas Gohr    /**
1497c54a0a6SAndreas Gohr     * Returns the ID and name to the wanted translation, empty
1507c54a0a6SAndreas Gohr     * $lng is default lang
151af1904f9SAndreas Gohr     */
152af1904f9SAndreas Gohr    function buildTransID($lng, $idpart) {
153af1904f9SAndreas Gohr        global $conf;
154af1904f9SAndreas Gohr        if($lng) {
1554e6ef383SGerry Weißbach            $link = ':' . $this->translationsNs . $lng . ':' . $idpart;
156af1904f9SAndreas Gohr            $name = $lng;
157af1904f9SAndreas Gohr        } else {
1584e6ef383SGerry Weißbach            $link = ':' . $this->translationsNs . $idpart;
15904971eeaSAndreas Gohr            $name = $this->realLC('');
160af1904f9SAndreas Gohr        }
161af1904f9SAndreas Gohr        return array($link, $name);
162af1904f9SAndreas Gohr    }
163af1904f9SAndreas Gohr
1641469199dSAndreas Gohr    /**
16504971eeaSAndreas Gohr     * Returns the real language code, even when an empty one is given
16604971eeaSAndreas Gohr     * (eg. resolves th default language)
16704971eeaSAndreas Gohr     */
16804971eeaSAndreas Gohr    function realLC($lc) {
16904971eeaSAndreas Gohr        global $conf;
17004971eeaSAndreas Gohr        if($lc) {
17104971eeaSAndreas Gohr            return $lc;
1720f9d57e2SGerry Weißbach        } elseif(empty($conf['lang_before_translation'])) {
17304971eeaSAndreas Gohr            return $conf['lang'];
17404971eeaSAndreas Gohr        } else {
17504971eeaSAndreas Gohr            return $conf['lang_before_translation'];
17604971eeaSAndreas Gohr        }
17704971eeaSAndreas Gohr    }
17804971eeaSAndreas Gohr
17904971eeaSAndreas Gohr    /**
18084877e9bSAndreas Gohr     * Check if current ID should be translated and any GUI
18184877e9bSAndreas Gohr     * should be shown
18284877e9bSAndreas Gohr     */
18384877e9bSAndreas Gohr    function istranslatable($id, $checkact = true) {
18484877e9bSAndreas Gohr        global $ACT;
18584877e9bSAndreas Gohr
186e5aa1ca2SGerry Weißbach        if(auth_isAdmin()) return true;
187e5aa1ca2SGerry Weißbach
18884877e9bSAndreas Gohr        if($checkact && $ACT != 'show') return false;
1894e6ef383SGerry Weißbach        if($this->translationsNs && strpos($id, $this->translationsNs) !== 0) return false;
19084877e9bSAndreas Gohr        $skiptrans = trim($this->getConf('skiptrans'));
19184877e9bSAndreas Gohr        if($skiptrans && preg_match('/' . $skiptrans . '/ui', ':' . $id)) return false;
19284877e9bSAndreas Gohr        $meta = p_get_metadata($id);
193e35b9849SMichael Grosse        if(!empty($meta['plugin']['translation']['notrans'])) return false;
19484877e9bSAndreas Gohr
19584877e9bSAndreas Gohr        return true;
19684877e9bSAndreas Gohr    }
19784877e9bSAndreas Gohr
19801dd7da9SAndreas Gohr    /**
19901dd7da9SAndreas Gohr     * Return the (localized) about link
20001dd7da9SAndreas Gohr     */
20101dd7da9SAndreas Gohr    function showAbout() {
202c9640767STomasz Tomasik        global $ID;
203c9640767STomasz Tomasik        global $conf;
204c9640767STomasz Tomasik        global $INFO;
205c9640767STomasz Tomasik
2065ad1c278SAndreas Gohr        $curlc = $this->getLangPart($ID);
207f34c9eb2SAndreas Gohr
208d0bdb959SAndreas Gohr        $about = $this->getConf('about');
209d0bdb959SAndreas Gohr        if($this->getConf('localabout')) {
210d0bdb959SAndreas Gohr            list($lc, $idpart) = $this->getTransParts($about);
211f34c9eb2SAndreas Gohr            list($about, $name) = $this->buildTransID($curlc, $idpart);
212d0bdb959SAndreas Gohr            $about = cleanID($about);
213d0bdb959SAndreas Gohr        }
214c9640767STomasz Tomasik
215c9640767STomasz Tomasik        $out = '';
216c9640767STomasz Tomasik        $out .= '<sup>';
217d0bdb959SAndreas Gohr        $out .= html_wikilink($about, '?');
218c9640767STomasz Tomasik        $out .= '</sup>';
219c9640767STomasz Tomasik
220c9640767STomasz Tomasik        return $out;
221c9640767STomasz Tomasik    }
222c9640767STomasz Tomasik
22384877e9bSAndreas Gohr    /**
224bbe70520SAndreas Gohr     * Returns a list of (lc => link) for all existing translations of a page
225bbe70520SAndreas Gohr     *
226bbe70520SAndreas Gohr     * @param $id
227bbe70520SAndreas Gohr     * @return array
228bbe70520SAndreas Gohr     */
229bbe70520SAndreas Gohr    function getAvailableTranslations($id) {
230bbe70520SAndreas Gohr        $result = array();
231bbe70520SAndreas Gohr
232bbe70520SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($id);
233bbe70520SAndreas Gohr        $lang = $this->realLC($lc);
234bbe70520SAndreas Gohr
2355e1f71acSGuillaume Turri        foreach($this->translations as $t) {
236bbe70520SAndreas Gohr            if($t == $lc) continue; //skip self
237bbe70520SAndreas Gohr            list($link, $name) = $this->buildTransID($t, $idpart);
238bbe70520SAndreas Gohr            if(page_exists($link)) {
239bbe70520SAndreas Gohr                $result[$name] = $link;
240bbe70520SAndreas Gohr            }
241bbe70520SAndreas Gohr        }
242bbe70520SAndreas Gohr
243bbe70520SAndreas Gohr        return $result;
244bbe70520SAndreas Gohr    }
245bbe70520SAndreas Gohr
246bbe70520SAndreas Gohr    /**
247649de279SAndreas Gohr     * Creates an UI for linking to the available and configured translations
248649de279SAndreas Gohr     *
249649de279SAndreas Gohr     * Can be called from the template or via the ~~TRANS~~ syntax component.
2501469199dSAndreas Gohr     */
251649de279SAndreas Gohr    public function showTranslations() {
2521469199dSAndreas Gohr        global $conf;
2531469199dSAndreas Gohr        global $INFO;
2541469199dSAndreas Gohr
255649de279SAndreas Gohr        if(!$this->istranslatable($INFO['id'])) return '';
25684877e9bSAndreas Gohr        $this->checkage();
2571469199dSAndreas Gohr
258649de279SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($INFO['id']);
25904971eeaSAndreas Gohr        $lang = $this->realLC($lc);
26039ecab8bSAndreas Gohr
2611469199dSAndreas Gohr        $out = '<div class="plugin_translation">';
262c9640767STomasz Tomasik
26304971eeaSAndreas Gohr        //show title and about
264c730e7ddSAndreas Gohr        if(isset($this->opts['title'])) {
2651469199dSAndreas Gohr            $out .= '<span>' . $this->getLang('translations');
2668bd452a3SAndreas Gohr            if($this->getConf('about')) $out .= $this->showAbout();
2671469199dSAndreas Gohr            $out .= ':</span> ';
268c730e7ddSAndreas Gohr            if(isset($this->opts['twolines'])) $out .= '<br />';
269c9640767STomasz Tomasik        }
2701469199dSAndreas Gohr
27104971eeaSAndreas Gohr        // open wrapper
27204971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
27304971eeaSAndreas Gohr            // select needs its own styling
2741469199dSAndreas Gohr            if($INFO['exists']) {
2751469199dSAndreas Gohr                $class = 'wikilink1';
2761469199dSAndreas Gohr            } else {
2771469199dSAndreas Gohr                $class = 'wikilink2';
2781469199dSAndreas Gohr            }
27904971eeaSAndreas Gohr            if(isset($this->opts['flag'])) {
28004971eeaSAndreas Gohr                $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
281649de279SAndreas Gohr            }else{
282649de279SAndreas Gohr                $flag = '';
283c9640767STomasz Tomasik            }
284649de279SAndreas Gohr
285fbc6382cSAndreas Gohr            if($conf['userewrite']) {
286fbc6382cSAndreas Gohr                $action = wl();
287fbc6382cSAndreas Gohr            } else {
288fbc6382cSAndreas Gohr                $action = script();
289fbc6382cSAndreas Gohr            }
290fbc6382cSAndreas Gohr
291fbc6382cSAndreas Gohr            $out .= '<form action="' . $action . '" id="translation__dropdown">';
29204971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" class="' . $class . '" /> ';
293c9640767STomasz Tomasik            $out .= '<select name="id" class="' . $class . '">';
29404971eeaSAndreas Gohr        } else {
29504971eeaSAndreas Gohr            $out .= '<ul>';
29604971eeaSAndreas Gohr        }
29704971eeaSAndreas Gohr
29804971eeaSAndreas Gohr        // insert items
2995e1f71acSGuillaume Turri        foreach($this->translations as $t) {
30004971eeaSAndreas Gohr            $out .= $this->getTransItem($t, $idpart);
30104971eeaSAndreas Gohr        }
30204971eeaSAndreas Gohr
30304971eeaSAndreas Gohr        // close wrapper
30404971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
3051469199dSAndreas Gohr            $out .= '</select>';
3061469199dSAndreas Gohr            $out .= '<input name="go" type="submit" value="&rarr;" />';
3071469199dSAndreas Gohr            $out .= '</form>';
30804971eeaSAndreas Gohr        } else {
3091469199dSAndreas Gohr            $out .= '</ul>';
3101469199dSAndreas Gohr        }
3111469199dSAndreas Gohr
31204971eeaSAndreas Gohr        // show about if not already shown
313c730e7ddSAndreas Gohr        if(!isset($this->opts['title']) && $this->getConf('about')) {
31404971eeaSAndreas Gohr            $out .= '&nbsp';
31504971eeaSAndreas Gohr            $out .= $this->showAbout();
31604971eeaSAndreas Gohr        }
31704971eeaSAndreas Gohr
3181469199dSAndreas Gohr        $out .= '</div>';
3191469199dSAndreas Gohr
3201469199dSAndreas Gohr        return $out;
3211469199dSAndreas Gohr    }
322af1904f9SAndreas Gohr
32301dd7da9SAndreas Gohr    /**
324bbe70520SAndreas Gohr     * Return the local name
325bbe70520SAndreas Gohr     *
326bbe70520SAndreas Gohr     * @param $lang
327bbe70520SAndreas Gohr     * @return string
328bbe70520SAndreas Gohr     */
329bbe70520SAndreas Gohr    function getLocalName($lang) {
330bbe70520SAndreas Gohr        if($this->LN[$lang]) {
331bbe70520SAndreas Gohr            return $this->LN[$lang];
332bbe70520SAndreas Gohr        }
333bbe70520SAndreas Gohr        return $lang;
334bbe70520SAndreas Gohr    }
335bbe70520SAndreas Gohr
336bbe70520SAndreas Gohr    /**
33701dd7da9SAndreas Gohr     * Create the link or option for a single translation
33801dd7da9SAndreas Gohr     *
33904971eeaSAndreas Gohr     * @param $lc string      The language code
34001dd7da9SAndreas Gohr     * @param $idpart string  The ID of the translated page
34104971eeaSAndreas Gohr     * @returns string        The item
34201dd7da9SAndreas Gohr     */
34304971eeaSAndreas Gohr    function getTransItem($lc, $idpart) {
344c9640767STomasz Tomasik        global $ID;
345c9640767STomasz Tomasik        global $conf;
346c9640767STomasz Tomasik
34704971eeaSAndreas Gohr        list($link, $lang) = $this->buildTransID($lc, $idpart);
348c9640767STomasz Tomasik        $link = cleanID($link);
34904971eeaSAndreas Gohr
35004971eeaSAndreas Gohr        // class
351c9640767STomasz Tomasik        if(page_exists($link, '', false)) {
352c9640767STomasz Tomasik            $class = 'wikilink1';
353c9640767STomasz Tomasik        } else {
354c9640767STomasz Tomasik            $class = 'wikilink2';
355c9640767STomasz Tomasik        }
356c9640767STomasz Tomasik
35704971eeaSAndreas Gohr        // local language name
358bbe70520SAndreas Gohr        $localname = $this->getLocalName($lang);
359c9640767STomasz Tomasik
36004971eeaSAndreas Gohr        // current?
36104971eeaSAndreas Gohr        if($ID == $link) {
36204971eeaSAndreas Gohr            $sel = ' selected="selected"';
36304971eeaSAndreas Gohr            $class .= ' cur';
36404971eeaSAndreas Gohr        } else {
36504971eeaSAndreas Gohr            $sel = '';
36604971eeaSAndreas Gohr        }
367c9640767STomasz Tomasik
36804971eeaSAndreas Gohr        // flag
3690f9d57e2SGerry Weißbach        $flag = $style = '';
37004971eeaSAndreas Gohr        if(isset($this->opts['flag'])) {
37104971eeaSAndreas Gohr            $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
37204971eeaSAndreas Gohr            $style = ' style="background-image: url(\'' . $flag . '\')"';
37304971eeaSAndreas Gohr            $class .= ' flag';
37404971eeaSAndreas Gohr        }
37504971eeaSAndreas Gohr
37604971eeaSAndreas Gohr        // what to display as name
37704971eeaSAndreas Gohr        if(isset($this->opts['name'])) {
37804971eeaSAndreas Gohr            $display = hsc($localname);
379c730e7ddSAndreas Gohr            if(isset($this->opts['langcode'])) $display .= ' (' . hsc($lang) . ')';
380c730e7ddSAndreas Gohr        } elseif(isset($this->opts['langcode'])) {
38104971eeaSAndreas Gohr            $display = hsc($lang);
38204971eeaSAndreas Gohr        } else {
38304971eeaSAndreas Gohr            $display = '&nbsp;';
38404971eeaSAndreas Gohr        }
38504971eeaSAndreas Gohr
38604971eeaSAndreas Gohr        // prepare output
38704971eeaSAndreas Gohr        $out = '';
38804971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
3892546b043SAndreas Gohr            if($conf['useslash']) $link = str_replace(':', '/', $link);
3902546b043SAndreas Gohr
39104971eeaSAndreas Gohr            $out .= '<option class="' . $class . '" title="' . hsc($localname) . '" value="' . $link . '"' . $sel . $style . '>';
39204971eeaSAndreas Gohr            $out .= $display;
39304971eeaSAndreas Gohr            $out .= '</option>';
39404971eeaSAndreas Gohr        } else {
395c9640767STomasz Tomasik            $out .= '<li><div class="li">';
396a4491becSGerry Weißbach            $out .= '<a href="' . wl($link, 'tns') . '" class="' . $class . '" title="' . hsc($localname) . '">';
39704971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" />';
39804971eeaSAndreas Gohr            $out .= $display;
399c9640767STomasz Tomasik            $out .= '</a>';
400c9640767STomasz Tomasik            $out .= '</div></li>';
401c9640767STomasz Tomasik        }
402c9640767STomasz Tomasik
403c9640767STomasz Tomasik        return $out;
404c9640767STomasz Tomasik    }
405c9640767STomasz Tomasik
40684877e9bSAndreas Gohr    /**
40784877e9bSAndreas Gohr     * Checks if the current page is a translation of a page
40884877e9bSAndreas Gohr     * in the default language. Displays a notice when it is
409eb6de668SMichael Große     * older than the original page. Tries to link to a diff
41084877e9bSAndreas Gohr     * with changes on the original since the translation
41184877e9bSAndreas Gohr     */
41284877e9bSAndreas Gohr    function checkage() {
41384877e9bSAndreas Gohr        global $ID;
41484877e9bSAndreas Gohr        global $INFO;
41584877e9bSAndreas Gohr        if(!$this->getConf('checkage')) return;
41684877e9bSAndreas Gohr        if(!$INFO['exists']) return;
41784877e9bSAndreas Gohr        $lng = $this->getLangPart($ID);
41884877e9bSAndreas Gohr        if($lng == $this->defaultlang) return;
419af1904f9SAndreas Gohr
4204e6ef383SGerry Weißbach        $rx = '/^' . $this->translationsNs . '((' . join('|', $this->translations) . '):)?/';
42184877e9bSAndreas Gohr        $idpart = preg_replace($rx, '', $ID);
42284877e9bSAndreas Gohr
42384877e9bSAndreas Gohr        // compare modification times
42484877e9bSAndreas Gohr        list($orig, $name) = $this->buildTransID($this->defaultlang, $idpart);
42584877e9bSAndreas Gohr        $origfn = wikiFN($orig);
42684877e9bSAndreas Gohr        if($INFO['lastmod'] >= @filemtime($origfn)) return;
42784877e9bSAndreas Gohr
42884877e9bSAndreas Gohr        // get revision from before translation
42984877e9bSAndreas Gohr        $orev = 0;
430cde89045SAndreas Gohr        $changelog = new PageChangelog($orig);
431cde89045SAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
43284877e9bSAndreas Gohr        foreach($revs as $rev) {
43384877e9bSAndreas Gohr            if($rev < $INFO['lastmod']) {
43484877e9bSAndreas Gohr                $orev = $rev;
43584877e9bSAndreas Gohr                break;
43684877e9bSAndreas Gohr            }
43784877e9bSAndreas Gohr        }
43884877e9bSAndreas Gohr
43944552920SAndreas Gohr        // see if the found revision still exists
44044552920SAndreas Gohr        if($orev && !page_exists($orig, $orev)) $orev = 0;
44144552920SAndreas Gohr
44284877e9bSAndreas Gohr        // build the message and display it
443dc3fbdb9SOleksiy Zagorskyi        $orig = cleanID($orig);
44484877e9bSAndreas Gohr        $msg = sprintf($this->getLang('outdated'), wl($orig));
445eb6de668SMichael Große
446eb6de668SMichael Große        $difflink = $this->getOldDiffLink($orig, $INFO['lastmod']);
447eb6de668SMichael Große        if ($difflink) {
448eb6de668SMichael Große            $msg .= sprintf(' ' . $this->getLang('diff'), $difflink);
44984877e9bSAndreas Gohr        }
45000431e1eSAndreas Gohr
45100431e1eSAndreas Gohr        echo '<div class="notify">' . $msg . '</div>';
45284877e9bSAndreas Gohr    }
453a4491becSGerry Weißbach
454eb6de668SMichael Große    function getOldDiffLink($id, $lastmod) {
455eb6de668SMichael Große        // get revision from before translation
456eb6de668SMichael Große        $orev = false;
457d530d9deSAndreas Gohr        $changelog = new PageChangelog($id);
458d530d9deSAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
459eb6de668SMichael Große        foreach($revs as $rev) {
460eb6de668SMichael Große            if($rev < $lastmod) {
461eb6de668SMichael Große                $orev = $rev;
462eb6de668SMichael Große                break;
463eb6de668SMichael Große            }
464eb6de668SMichael Große        }
465eb6de668SMichael Große        if($orev && !page_exists($id, $orev)) {
466eb6de668SMichael Große            return false;
467eb6de668SMichael Große        }
468eb6de668SMichael Große        $id = cleanID($id);
469eb6de668SMichael Große        return wl($id, array('do' => 'diff', 'rev' => $orev));
470eb6de668SMichael Große
471eb6de668SMichael Große    }
472*e33449a8SGerry Weißbach
473a4491becSGerry Weißbach    /**
474a4491becSGerry Weißbach     * Checks if the current ID has a translated page
475a4491becSGerry Weißbach     */
476a4491becSGerry Weißbach    function hasTranslation($inputID = null) {
477a4491becSGerry Weißbach        global $ID, $INFO, $conf;
478a4491becSGerry Weißbach
479a4491becSGerry Weißbach        if ( empty($inputID) )
480a4491becSGerry Weißbach        {
481a4491becSGerry Weißbach            $inputID = $ID;
482a4491becSGerry Weißbach        }
483a4491becSGerry Weißbach
484a4491becSGerry Weißbach        if ( !$this->istranslatable($id) ) return false;
485a4491becSGerry Weißbach
486a4491becSGerry Weißbach        $idpart = $this->getIDPart($inputID);
487a4491becSGerry Weißbach
4884e6ef383SGerry Weißbach        foreach($this->translations as $t)
489a4491becSGerry Weißbach        {
490a4491becSGerry Weißbach            list($link,$name) = $this->buildTransID($t,$idpart,false);
491a4491becSGerry Weißbach            $link = cleanID($link);
492a4491becSGerry Weißbach
493a4491becSGerry Weißbach            if( $inputID != $link && page_exists($link,'',false) ){
494a4491becSGerry Weißbach                return true;
495a4491becSGerry Weißbach            }
496a4491becSGerry Weißbach        }
497a4491becSGerry Weißbach
498a4491becSGerry Weißbach        return false;
499a4491becSGerry Weißbach    }
500af1904f9SAndreas Gohr}
501