xref: /plugin/autotranslation/action.php (revision 5fd0d0d1c6354560d100af5315ad8ff2bd24c576)
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 * @author     Guy Brand <gb@isis.u-strasbg.fr>
8 */
9
10// must be run within Dokuwiki
11if(!defined('DOKU_INC')) die();
12
13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
14require_once(DOKU_PLUGIN . 'action.php');
15
16class action_plugin_translation extends DokuWiki_Action_Plugin {
17
18    /**
19     * for th helper plugin
20     * @var helper_plugin_translation
21     */
22    var $hlp = null;
23
24    var $locale;
25
26    /**
27     * Constructor. Load helper plugin
28     */
29    function action_plugin_translation() {
30        $this->hlp =& plugin_load('helper', 'translation');
31    }
32
33    /**
34     * Registe the events
35     */
36    function register(&$controller) {
37        // should the lang be applied to UI?
38        $scriptName = basename($_SERVER['PHP_SELF']);
39        if($this->getConf('translateui')) {
40            switch($scriptName) {
41                case 'js.php':
42                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translation_js');
43                    $controller->register_hook('JS_CACHE_USE', 'BEFORE', $this, 'translation_jscache');
44                    break;
45
46                case 'ajax.php':
47                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translate_media_manager');
48                    break;
49
50                case 'mediamanager.php':
51                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
52                    break;
53
54                default:
55                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
56            }
57        }
58
59        if($scriptName !== 'js.php' && $scriptName !== 'ajax.php') {
60            $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'translation_hook');
61            $controller->register_hook('MEDIAMANAGER_STARTED', 'BEFORE', $this, 'translation_hook');
62        }
63
64        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'translation_search');
65        $controller->register_hook('COMMON_PAGETPL_LOAD', 'AFTER', $this, 'page_template_replacement');
66    }
67
68    /**
69     * Hook Callback. Make current language available as page template placeholder and handle
70     * original language copying
71     *
72     * @param $event
73     * @param $args
74     */
75    function page_template_replacement(&$event, $args) {
76        global $ID;
77
78        // load orginal content as template?
79        if($this->getConf('copytrans') && $this->hlp->istranslatable($ID, false)) {
80            // look for existing translations
81            $translations = $this->hlp->getAvailableTranslations($ID);
82            if($translations) {
83                // find original language (might've been provided via parameter or use first translation)
84                $orig = (string) $_REQUEST['fromlang'];
85                if(!$orig) $orig = array_shift(array_keys($translations));
86
87                // load file
88                $origfile = $translations[$orig];
89                $event->data['tpl'] = io_readFile(wikiFN($origfile));
90
91                // prefix with warning
92                $warn = io_readFile($this->localFN('totranslate'));
93                if($warn) $warn .= "\n\n";
94                $event->data['tpl'] = $warn . $event->data['tpl'];
95
96                // show user a choice of translations if any
97                if(count($translations) > 1) {
98                    $links = array();
99                    foreach($translations as $t => $l) {
100                        $links[] = '<a href="' . wl($ID, array('do' => 'edit', 'fromlang' => $t)) . '">' . $this->hlp->getLocalName($t) . '</a>';
101                    }
102
103                    msg(
104                        sprintf(
105                            $this->getLang('transloaded'),
106                            $this->hlp->getLocalName($orig),
107                            join(', ', $links)
108                        )
109                    );
110                }
111
112            }
113        }
114
115        // apply placeholders
116        $event->data['tpl'] = str_replace('@LANG@', $this->hlp->realLC(''), $event->data['tpl']);
117        $event->data['tpl'] = str_replace('@TRANS@', $this->hlp->getLangPart($ID), $event->data['tpl']);
118    }
119
120    /**
121     * Hook Callback. Load correct translation when loading JavaScript
122     *
123     * @param $event
124     * @param $args
125     */
126    function translation_js(&$event, $args) {
127        global $conf;
128        if(!isset($_GET['lang'])) return;
129        if(!in_array($_GET['lang'], $this->hlp->trans)) return;
130        $lang = $_GET['lang'];
131        $event->data = $lang;
132        $conf['lang'] = $lang;
133    }
134
135    /**
136     * Hook Callback. Pass language code to JavaScript dispatcher
137     *
138     * @param $event
139     * @param $args
140     * @return bool
141     */
142    function setJsCacheKey(&$event, $args) {
143        if(!isset($this->locale)) return false;
144        $count = count($event->data['script']);
145        for($i = 0; $i < $count; $i++) {
146            if(strpos($event->data['script'][$i]['src'], '/lib/exe/js.php') !== false) {
147                $event->data['script'][$i]['src'] .= '&lang=' . hsc($this->locale);
148            }
149        }
150
151        return false;
152    }
153
154    /**
155     * Hook Callback. Make sure the JavaScript is translation dependent
156     *
157     * @param $event
158     * @param $args
159     */
160    function translation_jscache(&$event, $args) {
161        if(!isset($_GET['lang'])) return;
162        if(!in_array($_GET['lang'], $this->hlp->trans)) return;
163
164        $lang = $_GET['lang'];
165        // reuse the constructor to reinitialize the cache key
166        $event->data->cache(
167            $event->data->key . $lang,
168            $event->data->ext
169        );
170    }
171
172    /**
173     * Hook Callback. Translate the AJAX loaded media manager
174     *
175     * @param $event
176     * @param $args
177     */
178    function translate_media_manager(&$event, $args) {
179        global $conf;
180        if(isset($_REQUEST['ID'])) {
181            $id = getID();
182            $lc = $this->hlp->getLangPart($id);
183        } elseif(isset($_SESSION[DOKU_COOKIE]['translationlc'])) {
184            $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
185        } else {
186            return;
187        }
188        $conf['lang'] = $lc;
189        $event->data = $lc;
190    }
191
192    /**
193     * Hook Callback. Change the UI language in foreign language namespaces
194     */
195    function translation_hook(&$event, $args) {
196        global $ID;
197        global $lang;
198        global $conf;
199        global $ACT;
200        // redirect away from start page?
201        if($this->conf['redirectstart'] && $ID == $conf['start'] && $ACT == 'show') {
202            $lc = $this->hlp->getBrowserLang();
203            if(!$lc) $lc = $conf['lang'];
204            header('Location: ' . wl($lc . ':' . $conf['start'], '', true, '&'));
205            exit;
206        }
207
208        // check if we are in a foreign language namespace
209        $lc = $this->hlp->getLangPart($ID);
210
211        // store language in session (for page related views only)
212        if(in_array($ACT, array('show', 'recent', 'diff', 'edit', 'preview', 'source', 'subscribe'))) {
213            $_SESSION[DOKU_COOKIE]['translationlc'] = $lc;
214        }
215        if(!$lc) $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
216        if(!$lc) return;
217        $this->locale = $lc;
218
219        if(!$this->getConf('translateui')) {
220            return true;
221        }
222
223        if(file_exists(DOKU_INC . 'inc/lang/' . $lc . '/lang.php')) {
224            require(DOKU_INC . 'inc/lang/' . $lc . '/lang.php');
225        }
226        $conf['lang_before_translation'] = $conf['lang']; //store for later access in syntax plugin
227        $conf['lang'] = $lc;
228
229        return true;
230    }
231
232    /**
233     * Hook Callback.  Resort page match results so that results are ordered by translation, having the
234     * default language first
235     */
236    function translation_search(&$event, $args) {
237
238        if($event->data['has_titles']) {
239            // sort into translation slots
240            $res = array();
241            foreach($event->result as $r => $t) {
242                $tr = $this->hlp->getLangPart($r);
243                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
244                $res["x$tr"][] = array($r, $t);
245            }
246            // sort by translations
247            ksort($res);
248            // combine
249            $event->result = array();
250            foreach($res as $r) {
251                foreach($r as $l) {
252                    $event->result[$l[0]] = $l[1];
253                }
254            }
255        } else {
256            # legacy support for old DokuWiki hooks
257
258            // sort into translation slots
259            $res = array();
260            foreach($event->result as $r) {
261                $tr = $this->hlp->getLangPart($r);
262                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
263                $res["x$tr"][] = $r;
264            }
265            // sort by translations
266            ksort($res);
267            // combine
268            $event->result = array();
269            foreach($res as $r) {
270                $event->result = array_merge($event->result, $r);
271            }
272        }
273    }
274
275}
276
277//Setup VIM: ex: et ts=4 :
278