xref: /plugin/autotranslation/helper.php (revision 39ecab8bea52cd31b538e8049b9d2c155c40f774)
1<?php
2/**
3 * Translation Plugin: Simple multilanguage plugin
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Andreas Gohr <andi@splitbrain.org>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class helper_plugin_translation extends DokuWiki_Plugin {
13    var $trans       = array();
14    var $tns         = '';
15    var $defaultlang = '';
16
17    /**
18     * Initialize
19     */
20    function helper_plugin_translation(){
21        global $conf;
22        require_once(DOKU_INC.'inc/pageutils.php');
23        require_once(DOKU_INC.'inc/utf8.php');
24
25        // load wanted translation into array
26        $this->trans = strtolower(str_replace(',',' ',$this->getConf('translations')));
27        $this->trans = array_unique(array_filter(explode(' ',$this->trans)));
28        sort($this->trans);
29
30        // get default translation
31        if(!$conf['lang_before_translation']){
32          $dfl = $conf['lang'];
33        } else {
34          $dfl = $conf['lang_before_translation'];
35        }
36        if(in_array($dfl,$this->trans)){
37            $this->defaultlang = $dfl;
38        }else{
39            $this->defaultlang = '';
40            array_unshift($this->trans,'');
41        }
42
43
44        $this->tns = cleanID($this->getConf('translationns'));
45        if($this->tns) $this->tns .= ':';
46    }
47
48    /**
49     * Check if the given ID is a translation and return the language code.
50     */
51    function getLangPart($id){
52        $rx = '/^'.$this->tns.'('.join('|',$this->trans).'):/';
53        if(preg_match($rx,$id,$match)){
54            return $match[1];
55        }
56        return '';
57    }
58
59    /**
60     * Returns the browser language if it matches with one of the configured
61     * languages
62     */
63    function getBrowserLang(){
64        $rx = '/(^|,|:|;|-)('.join('|',$this->trans).')($|,|:|;|-)/i';
65        if(preg_match($rx,$_SERVER['HTTP_ACCEPT_LANGUAGE'],$match)){
66            return strtolower($match[2]);
67        }
68        return false;
69    }
70
71
72    /**
73     * Returns the ID and name to the wanted translation, empty
74     * $lng is default lang
75     */
76    function buildTransID($lng,$idpart){
77        global $conf;
78        global $saved_conf;
79        if($lng){
80            $link = ':'.$this->tns.$lng.':'.$idpart;
81            $name = $lng;
82        }else{
83            $link = ':'.$this->tns.$idpart;
84            if(!$conf['lang_before_translation']){
85              $name = $conf['lang'];
86            } else {
87              $name = $conf['lang_before_translation'];
88            }
89        }
90        return array($link,$name);
91    }
92
93    /**
94     * Check if current ID should be translated and any GUI
95     * should be shown
96     */
97    function istranslatable($id,$checkact=true){
98        global $ACT;
99
100        if($checkact && $ACT != 'show') return false;
101        if($this->tns && strpos($id,$this->tns) !== 0) return false;
102        $skiptrans = trim($this->getConf('skiptrans'));
103        if($skiptrans &&  preg_match('/'.$skiptrans.'/ui',':'.$id)) return false;
104        $meta = p_get_metadata($id);
105        if($meta['plugin']['translation']['notrans']) return false;
106
107        return true;
108    }
109
110    /**
111     * Displays the available and configured translations. Needs to be placed in the template.
112     */
113    function showTranslations(){
114        global $ID;
115        global $conf;
116        global $INFO;
117
118        if(!$this->istranslatable($ID)) return;
119
120        $this->checkage();
121
122        $LN = confToHash(dirname(__FILE__).'/lang/langnames.txt');
123
124        $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/';
125        $idpart = preg_replace($rx,'',$ID);
126
127        $out  = '<div class="plugin_translation">';
128        $out .= '<span>'.$this->getLang('translations');
129        if($this->getConf('about')){
130            $out .= '<sup>'.html_wikilink($this->getConf('about'),'?').'</sup>';
131        }
132        $out .= ':</span> ';
133
134        if($this->getConf('dropdown')){ // use dropdown
135            if($INFO['exists']){
136                $class = 'wikilink1';
137            }else{
138                $class = 'wikilink2';
139            }
140            $out .= '<form action="'.wl().'" id="translation__dropdown">';
141            $out .= '<select name="id" class="'.$class.'">';
142            foreach($this->trans as $t){
143                list($link,$name) = $this->buildTransID($t,$idpart);
144                $link = cleanID($link);
145                if($ID == $link){
146                    $sel = ' selected="selected"';
147                }else{
148                    $sel = '';
149                }
150                if(page_exists($link,'',false)){
151                    $class = 'wikilink1';
152                }else{
153                    $class = 'wikilink2';
154                }
155                $out .= '<option value="'.$link.'"'.$sel.' class="'.$class.'" title="'.$LN[$name].'">'.hsc($name).'</option>';
156            }
157            $out .= '</select>';
158            $out .= '<input name="go" type="submit" value="&rarr;" />';
159            $out .= '</form>';
160        }else{ // use list
161            $out .= '<ul>';
162            foreach($this->trans as $t){
163                list($link,$name) = $this->buildTransID($t,$idpart);
164                if(page_exists($link,'',false)){
165                    $class = 'wikilink1';
166                }else{
167                    $class = 'wikilink2';
168                }
169                $out .= '  <li><div class="li"><a href="'.wl($link).'" class="'.$class.'" title="'.$LN[$name].'">'.hsc($name).'</a></div></li>';
170            }
171            $out .= '</ul>';
172        }
173
174        $out .= '</div>';
175
176        return $out;
177    }
178
179    /**
180     * Checks if the current page is a translation of a page
181     * in the default language. Displays a notice when it is
182     * older than the original page. Tries to lin to a diff
183     * with changes on the original since the translation
184     */
185    function checkage(){
186        global $ID;
187        global $INFO;
188        if(!$this->getConf('checkage')) return;
189        if(!$INFO['exists']) return;
190        $lng = $this->getLangPart($ID);
191        if($lng == $this->defaultlang) return;
192
193        $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/';
194        $idpart = preg_replace($rx,'',$ID);
195
196        // compare modification times
197        list($orig,$name) = $this->buildTransID($this->defaultlang,$idpart);
198        $origfn = wikiFN($orig);
199        if($INFO['lastmod'] >= @filemtime($origfn) ) return;
200
201        // get revision from before translation
202        $orev = 0;
203        $revs = getRevisions($orig,0,100);
204        foreach($revs as $rev){
205            if($rev < $INFO['lastmod']){
206                $orev = $rev;
207                break;
208            }
209        }
210
211        // see if the found revision still exists
212        if($orev && !page_exists($orig,$orev)) $orev=0;
213
214        // build the message and display it
215        $msg = sprintf($this->getLang('outdated'),wl($orig));
216        if($orev){
217            $msg .= sprintf(' '.$this->getLang('diff'),
218                    wl($orig,array('do'=>'diff','rev'=>$orev)));
219        }
220
221        echo '<div class="notify">'.$msg.'</div>';
222    }
223}
224