xref: /plugin/autotranslation/helper.php (revision d530d9dee369aa84f6f0a452588a704756d35e9e)
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
427c54a0a6SAndreas Gohr        if(!$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
545e1f71acSGuillaume Turri        $this->translationNs = cleanID($this->getConf('translationns'));
555e1f71acSGuillaume Turri        if($this->translationNs) $this->translationNs .= ':';
56af1904f9SAndreas Gohr    }
57af1904f9SAndreas Gohr
58af1904f9SAndreas Gohr    /**
59af1904f9SAndreas Gohr     * Check if the given ID is a translation and return the language code.
60af1904f9SAndreas Gohr     */
61af1904f9SAndreas Gohr    function getLangPart($id) {
6226522e09SAndreas Gohr        list($lng) = $this->getTransParts($id);
6326522e09SAndreas Gohr        return $lng;
64af1904f9SAndreas Gohr    }
6526522e09SAndreas Gohr
6626522e09SAndreas Gohr    /**
6726522e09SAndreas Gohr     * Check if the given ID is a translation and return the language code and
6826522e09SAndreas Gohr     * the id part.
6926522e09SAndreas Gohr     */
7026522e09SAndreas Gohr    function getTransParts($id) {
715e1f71acSGuillaume Turri        $rx = '/^' . $this->translationNs . '(' . join('|', $this->translations) . '):(.*)/';
7226522e09SAndreas Gohr        if(preg_match($rx, $id, $match)) {
7326522e09SAndreas Gohr            return array($match[1], $match[2]);
7426522e09SAndreas Gohr        }
7526522e09SAndreas Gohr        return array('', $id);
76af1904f9SAndreas Gohr    }
77af1904f9SAndreas Gohr
78af1904f9SAndreas Gohr    /**
797053cd66SAndreas Gohr     * Returns the browser language if it matches with one of the configured
807053cd66SAndreas Gohr     * languages
817053cd66SAndreas Gohr     */
827053cd66SAndreas Gohr    function getBrowserLang() {
835e1f71acSGuillaume Turri        $rx = '/(^|,|:|;|-)(' . join('|', $this->translations) . ')($|,|:|;|-)/i';
847053cd66SAndreas Gohr        if(preg_match($rx, $_SERVER['HTTP_ACCEPT_LANGUAGE'], $match)) {
857053cd66SAndreas Gohr            return strtolower($match[2]);
867053cd66SAndreas Gohr        }
877053cd66SAndreas Gohr        return false;
887053cd66SAndreas Gohr    }
897053cd66SAndreas Gohr
907053cd66SAndreas Gohr    /**
917c54a0a6SAndreas Gohr     * Returns the ID and name to the wanted translation, empty
927c54a0a6SAndreas Gohr     * $lng is default lang
93af1904f9SAndreas Gohr     */
94af1904f9SAndreas Gohr    function buildTransID($lng, $idpart) {
95af1904f9SAndreas Gohr        global $conf;
96af1904f9SAndreas Gohr        if($lng) {
975e1f71acSGuillaume Turri            $link = ':' . $this->translationNs . $lng . ':' . $idpart;
98af1904f9SAndreas Gohr            $name = $lng;
99af1904f9SAndreas Gohr        } else {
1005e1f71acSGuillaume Turri            $link = ':' . $this->translationNs . $idpart;
10104971eeaSAndreas Gohr            $name = $this->realLC('');
102af1904f9SAndreas Gohr        }
103af1904f9SAndreas Gohr        return array($link, $name);
104af1904f9SAndreas Gohr    }
105af1904f9SAndreas Gohr
1061469199dSAndreas Gohr    /**
10704971eeaSAndreas Gohr     * Returns the real language code, even when an empty one is given
10804971eeaSAndreas Gohr     * (eg. resolves th default language)
10904971eeaSAndreas Gohr     */
11004971eeaSAndreas Gohr    function realLC($lc) {
11104971eeaSAndreas Gohr        global $conf;
11204971eeaSAndreas Gohr        if($lc) {
11304971eeaSAndreas Gohr            return $lc;
11404971eeaSAndreas Gohr        } elseif(!$conf['lang_before_translation']) {
11504971eeaSAndreas Gohr            return $conf['lang'];
11604971eeaSAndreas Gohr        } else {
11704971eeaSAndreas Gohr            return $conf['lang_before_translation'];
11804971eeaSAndreas Gohr        }
11904971eeaSAndreas Gohr    }
12004971eeaSAndreas Gohr
12104971eeaSAndreas Gohr    /**
12284877e9bSAndreas Gohr     * Check if current ID should be translated and any GUI
12384877e9bSAndreas Gohr     * should be shown
12484877e9bSAndreas Gohr     */
12584877e9bSAndreas Gohr    function istranslatable($id, $checkact = true) {
12684877e9bSAndreas Gohr        global $ACT;
12784877e9bSAndreas Gohr
12884877e9bSAndreas Gohr        if($checkact && $ACT != 'show') return false;
1295e1f71acSGuillaume Turri        if($this->translationNs && strpos($id, $this->translationNs) !== 0) return false;
13084877e9bSAndreas Gohr        $skiptrans = trim($this->getConf('skiptrans'));
13184877e9bSAndreas Gohr        if($skiptrans && preg_match('/' . $skiptrans . '/ui', ':' . $id)) return false;
13284877e9bSAndreas Gohr        $meta = p_get_metadata($id);
13384877e9bSAndreas Gohr        if($meta['plugin']['translation']['notrans']) return false;
13484877e9bSAndreas Gohr
13584877e9bSAndreas Gohr        return true;
13684877e9bSAndreas Gohr    }
13784877e9bSAndreas Gohr
13801dd7da9SAndreas Gohr    /**
13901dd7da9SAndreas Gohr     * Return the (localized) about link
14001dd7da9SAndreas Gohr     */
14101dd7da9SAndreas Gohr    function showAbout() {
142c9640767STomasz Tomasik        global $ID;
143c9640767STomasz Tomasik        global $conf;
144c9640767STomasz Tomasik        global $INFO;
145c9640767STomasz Tomasik
1465ad1c278SAndreas Gohr        $curlc = $this->getLangPart($ID);
147f34c9eb2SAndreas Gohr
148d0bdb959SAndreas Gohr        $about = $this->getConf('about');
149d0bdb959SAndreas Gohr        if($this->getConf('localabout')) {
150d0bdb959SAndreas Gohr            list($lc, $idpart) = $this->getTransParts($about);
151f34c9eb2SAndreas Gohr            list($about, $name) = $this->buildTransID($curlc, $idpart);
152d0bdb959SAndreas Gohr            $about = cleanID($about);
153d0bdb959SAndreas Gohr        }
154c9640767STomasz Tomasik
155c9640767STomasz Tomasik        $out = '';
156c9640767STomasz Tomasik        $out .= '<sup>';
157d0bdb959SAndreas Gohr        $out .= html_wikilink($about, '?');
158c9640767STomasz Tomasik        $out .= '</sup>';
159c9640767STomasz Tomasik
160c9640767STomasz Tomasik        return $out;
161c9640767STomasz Tomasik    }
162c9640767STomasz Tomasik
16384877e9bSAndreas Gohr    /**
164bbe70520SAndreas Gohr     * Returns a list of (lc => link) for all existing translations of a page
165bbe70520SAndreas Gohr     *
166bbe70520SAndreas Gohr     * @param $id
167bbe70520SAndreas Gohr     * @return array
168bbe70520SAndreas Gohr     */
169bbe70520SAndreas Gohr    function getAvailableTranslations($id) {
170bbe70520SAndreas Gohr        $result = array();
171bbe70520SAndreas Gohr
172bbe70520SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($id);
173bbe70520SAndreas Gohr        $lang = $this->realLC($lc);
174bbe70520SAndreas Gohr
1755e1f71acSGuillaume Turri        foreach($this->translations as $t) {
176bbe70520SAndreas Gohr            if($t == $lc) continue; //skip self
177bbe70520SAndreas Gohr            list($link, $name) = $this->buildTransID($t, $idpart);
178bbe70520SAndreas Gohr            if(page_exists($link)) {
179bbe70520SAndreas Gohr                $result[$name] = $link;
180bbe70520SAndreas Gohr            }
181bbe70520SAndreas Gohr        }
182bbe70520SAndreas Gohr
183bbe70520SAndreas Gohr        return $result;
184bbe70520SAndreas Gohr    }
185bbe70520SAndreas Gohr
186bbe70520SAndreas Gohr    /**
187649de279SAndreas Gohr     * Creates an UI for linking to the available and configured translations
188649de279SAndreas Gohr     *
189649de279SAndreas Gohr     * Can be called from the template or via the ~~TRANS~~ syntax component.
1901469199dSAndreas Gohr     */
191649de279SAndreas Gohr    public function showTranslations() {
1921469199dSAndreas Gohr        global $conf;
1931469199dSAndreas Gohr        global $INFO;
1941469199dSAndreas Gohr
195649de279SAndreas Gohr        if(!$this->istranslatable($INFO['id'])) return '';
19684877e9bSAndreas Gohr        $this->checkage();
1971469199dSAndreas Gohr
198649de279SAndreas Gohr        list($lc, $idpart) = $this->getTransParts($INFO['id']);
19904971eeaSAndreas Gohr        $lang = $this->realLC($lc);
20039ecab8bSAndreas Gohr
2011469199dSAndreas Gohr        $out = '<div class="plugin_translation">';
202c9640767STomasz Tomasik
20304971eeaSAndreas Gohr        //show title and about
204c730e7ddSAndreas Gohr        if(isset($this->opts['title'])) {
2051469199dSAndreas Gohr            $out .= '<span>' . $this->getLang('translations');
2068bd452a3SAndreas Gohr            if($this->getConf('about')) $out .= $this->showAbout();
2071469199dSAndreas Gohr            $out .= ':</span> ';
208c730e7ddSAndreas Gohr            if(isset($this->opts['twolines'])) $out .= '<br />';
209c9640767STomasz Tomasik        }
2101469199dSAndreas Gohr
21104971eeaSAndreas Gohr        // open wrapper
21204971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
21304971eeaSAndreas Gohr            // select needs its own styling
2141469199dSAndreas Gohr            if($INFO['exists']) {
2151469199dSAndreas Gohr                $class = 'wikilink1';
2161469199dSAndreas Gohr            } else {
2171469199dSAndreas Gohr                $class = 'wikilink2';
2181469199dSAndreas Gohr            }
21904971eeaSAndreas Gohr            if(isset($this->opts['flag'])) {
22004971eeaSAndreas Gohr                $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
221649de279SAndreas Gohr            }else{
222649de279SAndreas Gohr                $flag = '';
223c9640767STomasz Tomasik            }
224649de279SAndreas Gohr
225fbc6382cSAndreas Gohr            if($conf['userewrite']) {
226fbc6382cSAndreas Gohr                $action = wl();
227fbc6382cSAndreas Gohr            } else {
228fbc6382cSAndreas Gohr                $action = script();
229fbc6382cSAndreas Gohr            }
230fbc6382cSAndreas Gohr
231fbc6382cSAndreas Gohr            $out .= '<form action="' . $action . '" id="translation__dropdown">';
23204971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" class="' . $class . '" /> ';
233c9640767STomasz Tomasik            $out .= '<select name="id" class="' . $class . '">';
23404971eeaSAndreas Gohr        } else {
23504971eeaSAndreas Gohr            $out .= '<ul>';
23604971eeaSAndreas Gohr        }
23704971eeaSAndreas Gohr
23804971eeaSAndreas Gohr        // insert items
2395e1f71acSGuillaume Turri        foreach($this->translations as $t) {
24004971eeaSAndreas Gohr            $out .= $this->getTransItem($t, $idpart);
24104971eeaSAndreas Gohr        }
24204971eeaSAndreas Gohr
24304971eeaSAndreas Gohr        // close wrapper
24404971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
2451469199dSAndreas Gohr            $out .= '</select>';
2461469199dSAndreas Gohr            $out .= '<input name="go" type="submit" value="&rarr;" />';
2471469199dSAndreas Gohr            $out .= '</form>';
24804971eeaSAndreas Gohr        } else {
2491469199dSAndreas Gohr            $out .= '</ul>';
2501469199dSAndreas Gohr        }
2511469199dSAndreas Gohr
25204971eeaSAndreas Gohr        // show about if not already shown
253c730e7ddSAndreas Gohr        if(!isset($this->opts['title']) && $this->getConf('about')) {
25404971eeaSAndreas Gohr            $out .= '&nbsp';
25504971eeaSAndreas Gohr            $out .= $this->showAbout();
25604971eeaSAndreas Gohr        }
25704971eeaSAndreas Gohr
2581469199dSAndreas Gohr        $out .= '</div>';
2591469199dSAndreas Gohr
2601469199dSAndreas Gohr        return $out;
2611469199dSAndreas Gohr    }
262af1904f9SAndreas Gohr
26301dd7da9SAndreas Gohr    /**
264bbe70520SAndreas Gohr     * Return the local name
265bbe70520SAndreas Gohr     *
266bbe70520SAndreas Gohr     * @param $lang
267bbe70520SAndreas Gohr     * @return string
268bbe70520SAndreas Gohr     */
269bbe70520SAndreas Gohr    function getLocalName($lang) {
270bbe70520SAndreas Gohr        if($this->LN[$lang]) {
271bbe70520SAndreas Gohr            return $this->LN[$lang];
272bbe70520SAndreas Gohr        }
273bbe70520SAndreas Gohr        return $lang;
274bbe70520SAndreas Gohr    }
275bbe70520SAndreas Gohr
276bbe70520SAndreas Gohr    /**
27701dd7da9SAndreas Gohr     * Create the link or option for a single translation
27801dd7da9SAndreas Gohr     *
27904971eeaSAndreas Gohr     * @param $lc string      The language code
28001dd7da9SAndreas Gohr     * @param $idpart string  The ID of the translated page
28104971eeaSAndreas Gohr     * @returns string        The item
28201dd7da9SAndreas Gohr     */
28304971eeaSAndreas Gohr    function getTransItem($lc, $idpart) {
284c9640767STomasz Tomasik        global $ID;
285c9640767STomasz Tomasik        global $conf;
286c9640767STomasz Tomasik
28704971eeaSAndreas Gohr        list($link, $lang) = $this->buildTransID($lc, $idpart);
288c9640767STomasz Tomasik        $link = cleanID($link);
28904971eeaSAndreas Gohr
29004971eeaSAndreas Gohr        // class
291c9640767STomasz Tomasik        if(page_exists($link, '', false)) {
292c9640767STomasz Tomasik            $class = 'wikilink1';
293c9640767STomasz Tomasik        } else {
294c9640767STomasz Tomasik            $class = 'wikilink2';
295c9640767STomasz Tomasik        }
296c9640767STomasz Tomasik
29704971eeaSAndreas Gohr        // local language name
298bbe70520SAndreas Gohr        $localname = $this->getLocalName($lang);
299c9640767STomasz Tomasik
30004971eeaSAndreas Gohr        // current?
30104971eeaSAndreas Gohr        if($ID == $link) {
30204971eeaSAndreas Gohr            $sel = ' selected="selected"';
30304971eeaSAndreas Gohr            $class .= ' cur';
30404971eeaSAndreas Gohr        } else {
30504971eeaSAndreas Gohr            $sel = '';
30604971eeaSAndreas Gohr        }
307c9640767STomasz Tomasik
30804971eeaSAndreas Gohr        // flag
30904971eeaSAndreas Gohr        if(isset($this->opts['flag'])) {
31004971eeaSAndreas Gohr            $flag = DOKU_BASE . 'lib/plugins/translation/flags/' . hsc($lang) . '.gif';
31104971eeaSAndreas Gohr            $style = ' style="background-image: url(\'' . $flag . '\')"';
31204971eeaSAndreas Gohr            $class .= ' flag';
31304971eeaSAndreas Gohr        }
31404971eeaSAndreas Gohr
31504971eeaSAndreas Gohr        // what to display as name
31604971eeaSAndreas Gohr        if(isset($this->opts['name'])) {
31704971eeaSAndreas Gohr            $display = hsc($localname);
318c730e7ddSAndreas Gohr            if(isset($this->opts['langcode'])) $display .= ' (' . hsc($lang) . ')';
319c730e7ddSAndreas Gohr        } elseif(isset($this->opts['langcode'])) {
32004971eeaSAndreas Gohr            $display = hsc($lang);
32104971eeaSAndreas Gohr        } else {
32204971eeaSAndreas Gohr            $display = '&nbsp;';
32304971eeaSAndreas Gohr        }
32404971eeaSAndreas Gohr
32504971eeaSAndreas Gohr        // prepare output
32604971eeaSAndreas Gohr        $out = '';
32704971eeaSAndreas Gohr        if($this->getConf('dropdown')) {
3282546b043SAndreas Gohr            if($conf['useslash']) $link = str_replace(':', '/', $link);
3292546b043SAndreas Gohr
33004971eeaSAndreas Gohr            $out .= '<option class="' . $class . '" title="' . hsc($localname) . '" value="' . $link . '"' . $sel . $style . '>';
33104971eeaSAndreas Gohr            $out .= $display;
33204971eeaSAndreas Gohr            $out .= '</option>';
33304971eeaSAndreas Gohr        } else {
334c9640767STomasz Tomasik            $out .= '<li><div class="li">';
33537140606SAndreas Gohr            $out .= '<a href="' . wl($link) . '" class="' . $class . '" title="' . hsc($localname) . '">';
33604971eeaSAndreas Gohr            if($flag) $out .= '<img src="' . $flag . '" alt="' . hsc($lang) . '" height="11" />';
33704971eeaSAndreas Gohr            $out .= $display;
338c9640767STomasz Tomasik            $out .= '</a>';
339c9640767STomasz Tomasik            $out .= '</div></li>';
340c9640767STomasz Tomasik        }
341c9640767STomasz Tomasik
342c9640767STomasz Tomasik        return $out;
343c9640767STomasz Tomasik    }
344c9640767STomasz Tomasik
34584877e9bSAndreas Gohr    /**
34684877e9bSAndreas Gohr     * Checks if the current page is a translation of a page
34784877e9bSAndreas Gohr     * in the default language. Displays a notice when it is
348eb6de668SMichael Große     * older than the original page. Tries to link to a diff
34984877e9bSAndreas Gohr     * with changes on the original since the translation
35084877e9bSAndreas Gohr     */
35184877e9bSAndreas Gohr    function checkage() {
35284877e9bSAndreas Gohr        global $ID;
35384877e9bSAndreas Gohr        global $INFO;
35484877e9bSAndreas Gohr        if(!$this->getConf('checkage')) return;
35584877e9bSAndreas Gohr        if(!$INFO['exists']) return;
35684877e9bSAndreas Gohr        $lng = $this->getLangPart($ID);
35784877e9bSAndreas Gohr        if($lng == $this->defaultlang) return;
358af1904f9SAndreas Gohr
3595e1f71acSGuillaume Turri        $rx = '/^' . $this->translationNs . '((' . join('|', $this->translations) . '):)?/';
36084877e9bSAndreas Gohr        $idpart = preg_replace($rx, '', $ID);
36184877e9bSAndreas Gohr
36284877e9bSAndreas Gohr        // compare modification times
36384877e9bSAndreas Gohr        list($orig, $name) = $this->buildTransID($this->defaultlang, $idpart);
36484877e9bSAndreas Gohr        $origfn = wikiFN($orig);
36584877e9bSAndreas Gohr        if($INFO['lastmod'] >= @filemtime($origfn)) return;
36684877e9bSAndreas Gohr
36784877e9bSAndreas Gohr        // get revision from before translation
36884877e9bSAndreas Gohr        $orev = 0;
369cde89045SAndreas Gohr        $changelog = new PageChangelog($orig);
370cde89045SAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
37184877e9bSAndreas Gohr        foreach($revs as $rev) {
37284877e9bSAndreas Gohr            if($rev < $INFO['lastmod']) {
37384877e9bSAndreas Gohr                $orev = $rev;
37484877e9bSAndreas Gohr                break;
37584877e9bSAndreas Gohr            }
37684877e9bSAndreas Gohr        }
37784877e9bSAndreas Gohr
37844552920SAndreas Gohr        // see if the found revision still exists
37944552920SAndreas Gohr        if($orev && !page_exists($orig, $orev)) $orev = 0;
38044552920SAndreas Gohr
38184877e9bSAndreas Gohr        // build the message and display it
382dc3fbdb9SOleksiy Zagorskyi        $orig = cleanID($orig);
38384877e9bSAndreas Gohr        $msg = sprintf($this->getLang('outdated'), wl($orig));
384eb6de668SMichael Große
385eb6de668SMichael Große        $difflink = $this->getOldDiffLink($orig, $INFO['lastmod']);
386eb6de668SMichael Große        if ($difflink) {
387eb6de668SMichael Große            $msg .= sprintf(' ' . $this->getLang('diff'), $difflink);
38884877e9bSAndreas Gohr        }
38900431e1eSAndreas Gohr
39000431e1eSAndreas Gohr        echo '<div class="notify">' . $msg . '</div>';
39184877e9bSAndreas Gohr    }
392eb6de668SMichael Große
393eb6de668SMichael Große    function getOldDiffLink($id, $lastmod) {
394eb6de668SMichael Große        // get revision from before translation
395eb6de668SMichael Große        $orev = false;
396*d530d9deSAndreas Gohr        $changelog = new PageChangelog($id);
397*d530d9deSAndreas Gohr        $revs = $changelog->getRevisions(0, 100);
398eb6de668SMichael Große        foreach($revs as $rev) {
399eb6de668SMichael Große            if($rev < $lastmod) {
400eb6de668SMichael Große                $orev = $rev;
401eb6de668SMichael Große                break;
402eb6de668SMichael Große            }
403eb6de668SMichael Große        }
404eb6de668SMichael Große        if($orev && !page_exists($id, $orev)) {
405eb6de668SMichael Große            return false;
406eb6de668SMichael Große        }
407eb6de668SMichael Große        $id = cleanID($id);
408eb6de668SMichael Große        return wl($id, array('do' => 'diff', 'rev' => $orev));
409eb6de668SMichael Große
410eb6de668SMichael Große    }
411af1904f9SAndreas Gohr}
412