xref: /plugin/autotranslation/helper.php (revision dc3fbdb9e3974e6de067f094e7e9e310d36541d1)
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		$link = cleanID($link);
165                if(page_exists($link,'',false)){
166                    $class = 'wikilink1';
167                }else{
168                    $class = 'wikilink2';
169                }
170                $out .= '  <li><div class="li"><a href="'.wl($link).'" class="'.$class.'" title="'.$LN[$name].'">'.hsc($name).'</a></div></li>';
171            }
172            $out .= '</ul>';
173        }
174
175        $out .= '</div>';
176
177        return $out;
178    }
179
180    /**
181     * Checks if the current page is a translation of a page
182     * in the default language. Displays a notice when it is
183     * older than the original page. Tries to lin to a diff
184     * with changes on the original since the translation
185     */
186    function checkage(){
187        global $ID;
188        global $INFO;
189        if(!$this->getConf('checkage')) return;
190        if(!$INFO['exists']) return;
191        $lng = $this->getLangPart($ID);
192        if($lng == $this->defaultlang) return;
193
194        $rx = '/^'.$this->tns.'(('.join('|',$this->trans).'):)?/';
195        $idpart = preg_replace($rx,'',$ID);
196
197        // compare modification times
198        list($orig,$name) = $this->buildTransID($this->defaultlang,$idpart);
199        $origfn = wikiFN($orig);
200        if($INFO['lastmod'] >= @filemtime($origfn) ) return;
201
202        // get revision from before translation
203        $orev = 0;
204        $revs = getRevisions($orig,0,100);
205        foreach($revs as $rev){
206            if($rev < $INFO['lastmod']){
207                $orev = $rev;
208                break;
209            }
210        }
211
212        // see if the found revision still exists
213        if($orev && !page_exists($orig,$orev)) $orev=0;
214
215        // build the message and display it
216        $orig = cleanID($orig);
217        $msg = sprintf($this->getLang('outdated'),wl($orig));
218        if($orev){
219            $msg .= sprintf(' '.$this->getLang('diff'),
220                    wl($orig,array('do'=>'diff','rev'=>$orev)));
221        }
222
223        echo '<div class="notify">'.$msg.'</div>';
224    }
225}
226