xref: /plugin/autotranslation/action.php (revision bbe70520dcd3cf7c23d4a37b312b69b9c4aebd37)
10a7415d3SAndreas Gohr<?php
20a7415d3SAndreas Gohr/**
3af1904f9SAndreas Gohr * Translation Plugin: Simple multilanguage plugin
40a7415d3SAndreas Gohr *
50a7415d3SAndreas Gohr * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
60a7415d3SAndreas Gohr * @author     Andreas Gohr <andi@splitbrain.org>
70a7415d3SAndreas Gohr * @author     Guy Brand <gb@isis.u-strasbg.fr>
80a7415d3SAndreas Gohr */
90a7415d3SAndreas Gohr
100a7415d3SAndreas Gohr// must be run within Dokuwiki
110a7415d3SAndreas Gohrif(!defined('DOKU_INC')) die();
120a7415d3SAndreas Gohr
130a7415d3SAndreas Gohrif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
140a7415d3SAndreas Gohrrequire_once(DOKU_PLUGIN.'action.php');
150a7415d3SAndreas Gohr
160a7415d3SAndreas Gohrclass action_plugin_translation extends DokuWiki_Action_Plugin {
170a7415d3SAndreas Gohr
180a7415d3SAndreas Gohr    /**
19af1904f9SAndreas Gohr     * for th helper plugin
20cabcc95dSDominik Eckelmann     * @var helper_plugin_translation
21af1904f9SAndreas Gohr     */
22af1904f9SAndreas Gohr    var $hlp = null;
23af1904f9SAndreas Gohr
24ec6cbde6SDominik Eckelmann    var $locale;
25ec6cbde6SDominik Eckelmann
26af1904f9SAndreas Gohr    /**
27af1904f9SAndreas Gohr     * Constructor. Load helper plugin
28af1904f9SAndreas Gohr     */
29af1904f9SAndreas Gohr    function action_plugin_translation(){
30af1904f9SAndreas Gohr        $this->hlp =& plugin_load('helper', 'translation');
31af1904f9SAndreas Gohr    }
32af1904f9SAndreas Gohr
33af1904f9SAndreas Gohr    /**
340a7415d3SAndreas Gohr     * Registe the events
350a7415d3SAndreas Gohr     */
360a7415d3SAndreas Gohr    function register(&$controller) {
370a7415d3SAndreas Gohr        // should the lang be applied to UI?
38ec6cbde6SDominik Eckelmann        $scriptName = basename($_SERVER['PHP_SELF']);
3934591120SDominik Eckelmann        if($this->getConf('translateui')){
40ec6cbde6SDominik Eckelmann            switch ($scriptName) {
41ec6cbde6SDominik Eckelmann                case 'js.php':
42ec6cbde6SDominik Eckelmann                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translation_js');
43db7c51b4SAndreas Gohr                    $controller->register_hook('JS_CACHE_USE', 'BEFORE', $this, 'translation_jscache');
44ec6cbde6SDominik Eckelmann                    break;
45ec6cbde6SDominik Eckelmann
46ec6cbde6SDominik Eckelmann                case 'ajax.php':
47ec6cbde6SDominik Eckelmann                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translate_media_manager');
48ec6cbde6SDominik Eckelmann                    break;
49ec6cbde6SDominik Eckelmann
50ec6cbde6SDominik Eckelmann                case 'mediamanager.php':
51ec6cbde6SDominik Eckelmann                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
52ec6cbde6SDominik Eckelmann                    break;
53ec6cbde6SDominik Eckelmann
54ec6cbde6SDominik Eckelmann                default:
55ec6cbde6SDominik Eckelmann                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
56ec6cbde6SDominik Eckelmann            }
570a7415d3SAndreas Gohr        }
5834591120SDominik Eckelmann
5934591120SDominik Eckelmann        if ($scriptName !== 'js.php' && $scriptName !== 'ajax.php') {
6034591120SDominik Eckelmann            $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'translation_hook');
6134591120SDominik Eckelmann            $controller->register_hook('MEDIAMANAGER_STARTED', 'BEFORE', $this, 'translation_hook');
6234591120SDominik Eckelmann        }
6334591120SDominik Eckelmann
64af1904f9SAndreas Gohr        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'translation_search');
65cabcc95dSDominik Eckelmann        $controller->register_hook('COMMON_PAGETPL_LOAD', 'AFTER', $this, 'page_template_replacement');
66cabcc95dSDominik Eckelmann    }
67cabcc95dSDominik Eckelmann
68*bbe70520SAndreas Gohr    /**
69*bbe70520SAndreas Gohr     * Hook Callback. Make current language available as page template placeholder and handle
70*bbe70520SAndreas Gohr     * original language copying
71*bbe70520SAndreas Gohr     *
72*bbe70520SAndreas Gohr     * @param $event
73*bbe70520SAndreas Gohr     * @param $args
74*bbe70520SAndreas Gohr     */
75cabcc95dSDominik Eckelmann    function page_template_replacement(&$event, $args) {
76cabcc95dSDominik Eckelmann        global $ID;
77*bbe70520SAndreas Gohr
78*bbe70520SAndreas Gohr        // load orginal content as template?
79*bbe70520SAndreas Gohr        if($this->getConf('copytrans') && $this->hlp->istranslatable($ID, false)) {
80*bbe70520SAndreas Gohr            // look for existing translations
81*bbe70520SAndreas Gohr            $translations = $this->hlp->getAvailableTranslations($ID);
82*bbe70520SAndreas Gohr            if($translations) {
83*bbe70520SAndreas Gohr                // find original language (might've been provided via parameter or use first translation)
84*bbe70520SAndreas Gohr                $orig = (string) $_REQUEST['fromlang'];
85*bbe70520SAndreas Gohr                if(!$orig) $orig = array_shift(array_keys($translations));
86*bbe70520SAndreas Gohr
87*bbe70520SAndreas Gohr                // load file
88*bbe70520SAndreas Gohr                $origfile = $translations[$orig];
89*bbe70520SAndreas Gohr                $event->data['tpl'] = io_readFile(wikiFN($origfile));
90*bbe70520SAndreas Gohr
91*bbe70520SAndreas Gohr                // prefix with warning
92*bbe70520SAndreas Gohr                $warn = io_readFile($this->localFN('totranslate'));
93*bbe70520SAndreas Gohr                if($warn) $warn .= "\n\n";
94*bbe70520SAndreas Gohr                $event->data['tpl'] = $warn . $event->data['tpl'];
95*bbe70520SAndreas Gohr
96*bbe70520SAndreas Gohr                // show user a choice of translations if any
97*bbe70520SAndreas Gohr                if(count($translations) > 1){
98*bbe70520SAndreas Gohr                    $links = array();
99*bbe70520SAndreas Gohr                    foreach($translations as $t => $l){
100*bbe70520SAndreas Gohr                        $links[] = '<a href="'.wl($ID,array('do'=>edit,'fromlang'=>$t)).'">'.$this->hlp->getLocalName($t).'</a>';
101*bbe70520SAndreas Gohr                    }
102*bbe70520SAndreas Gohr
103*bbe70520SAndreas Gohr                    msg(sprintf(
104*bbe70520SAndreas Gohr                            $this->getLang('transloaded'),
105*bbe70520SAndreas Gohr                            $this->hlp->getLocalName($orig),
106*bbe70520SAndreas Gohr                            join(', ', $links)
107*bbe70520SAndreas Gohr                        )
108*bbe70520SAndreas Gohr                    );
109*bbe70520SAndreas Gohr                }
110*bbe70520SAndreas Gohr
111*bbe70520SAndreas Gohr
112*bbe70520SAndreas Gohr            }
113*bbe70520SAndreas Gohr        }
114*bbe70520SAndreas Gohr
115*bbe70520SAndreas Gohr        // apply placeholders
116cabcc95dSDominik Eckelmann        $event->data['tpl'] = str_replace('@LANG@', $this->hlp->realLC(''), $event->data['tpl']);
117cabcc95dSDominik Eckelmann        $event->data['tpl'] = str_replace('@TRANS@', $this->hlp->getLangPart($ID), $event->data['tpl']);
1180a7415d3SAndreas Gohr    }
1190a7415d3SAndreas Gohr
120*bbe70520SAndreas Gohr
121*bbe70520SAndreas Gohr    /**
122*bbe70520SAndreas Gohr     * Hook Callback. Load correct translation when loading JavaScript
123*bbe70520SAndreas Gohr     *
124*bbe70520SAndreas Gohr     * @param $event
125*bbe70520SAndreas Gohr     * @param $args
126*bbe70520SAndreas Gohr     */
127*bbe70520SAndreas Gohr    function translation_js(&$event, $args) {
128*bbe70520SAndreas Gohr        global $conf;
129*bbe70520SAndreas Gohr        if(!isset($_GET['lang'])) return;
130*bbe70520SAndreas Gohr        if(!in_array($_GET['lang'],$this->hlp->trans)) return;
131*bbe70520SAndreas Gohr        $lang = $_GET['lang'];
132*bbe70520SAndreas Gohr        $event->data = $lang;
133*bbe70520SAndreas Gohr        $conf['lang'] = $lang;
134*bbe70520SAndreas Gohr    }
135*bbe70520SAndreas Gohr
136*bbe70520SAndreas Gohr    /**
137*bbe70520SAndreas Gohr     * Hook Callback. Pass language code to JavaScript dispatcher
138*bbe70520SAndreas Gohr     *
139*bbe70520SAndreas Gohr     * @param $event
140*bbe70520SAndreas Gohr     * @param $args
141*bbe70520SAndreas Gohr     * @return bool
142*bbe70520SAndreas Gohr     */
143ec6cbde6SDominik Eckelmann    function setJsCacheKey(&$event, $args) {
144ec6cbde6SDominik Eckelmann        if (!isset($this->locale)) return false;
145ec6cbde6SDominik Eckelmann        $count = count($event->data['script']);
146ec6cbde6SDominik Eckelmann        for ($i = 0; $i<$count; $i++) {
147ec6cbde6SDominik Eckelmann            if (strpos($event->data['script'][$i]['src'], '/lib/exe/js.php') !== false) {
148db7c51b4SAndreas Gohr                $event->data['script'][$i]['src'] .= '&lang='.hsc($this->locale);
149ec6cbde6SDominik Eckelmann            }
150ec6cbde6SDominik Eckelmann        }
151ec6cbde6SDominik Eckelmann
152ec6cbde6SDominik Eckelmann        return false;
153ec6cbde6SDominik Eckelmann    }
154ec6cbde6SDominik Eckelmann
155*bbe70520SAndreas Gohr    /**
156*bbe70520SAndreas Gohr     * Hook Callback. Make sure the JavaScript is translation dependent
157*bbe70520SAndreas Gohr     *
158*bbe70520SAndreas Gohr     * @param $event
159*bbe70520SAndreas Gohr     * @param $args
160*bbe70520SAndreas Gohr     */
161db7c51b4SAndreas Gohr    function translation_jscache(&$event, $args) {
162db7c51b4SAndreas Gohr        if (!isset($_GET['lang'])) return;
163db7c51b4SAndreas Gohr        if(!in_array($_GET['lang'],$this->hlp->trans)) return;
164db7c51b4SAndreas Gohr
165db7c51b4SAndreas Gohr        $lang = $_GET['lang'];
166db7c51b4SAndreas Gohr        // reuse the constructor to reinitialize the cache key
167db7c51b4SAndreas Gohr        $event->data->cache(
168db7c51b4SAndreas Gohr            $event->data->key . $lang,
169db7c51b4SAndreas Gohr            $event->data->ext
170db7c51b4SAndreas Gohr        );
171ec6cbde6SDominik Eckelmann    }
172ec6cbde6SDominik Eckelmann
173*bbe70520SAndreas Gohr    /**
174*bbe70520SAndreas Gohr     * Hook Callback. Translate the AJAX loaded media manager
175*bbe70520SAndreas Gohr     *
176*bbe70520SAndreas Gohr     * @param $event
177*bbe70520SAndreas Gohr     * @param $args
178*bbe70520SAndreas Gohr     */
179ec6cbde6SDominik Eckelmann    function translate_media_manager(&$event, $args) {
180ec6cbde6SDominik Eckelmann        global $conf;
181ec6cbde6SDominik Eckelmann        if (isset($_REQUEST['ID'])) {
182ec6cbde6SDominik Eckelmann            $id = getID();
183ec6cbde6SDominik Eckelmann            $lc = $this->hlp->getLangPart($id);
184ec6cbde6SDominik Eckelmann        } elseif (isset($_SESSION[DOKU_COOKIE]['translationlc'])) {
185ec6cbde6SDominik Eckelmann            $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
186ec6cbde6SDominik Eckelmann        } else {
187db7c51b4SAndreas Gohr            return;
188ec6cbde6SDominik Eckelmann        }
189ec6cbde6SDominik Eckelmann        $conf['lang'] = $lc;
190ec6cbde6SDominik Eckelmann        $event->data = $lc;
191ec6cbde6SDominik Eckelmann    }
192ec6cbde6SDominik Eckelmann
1930a7415d3SAndreas Gohr    /**
194*bbe70520SAndreas Gohr     * Hook Callback. Change the UI language in foreign language namespaces
1950a7415d3SAndreas Gohr     */
1960a7415d3SAndreas Gohr    function translation_hook(&$event, $args) {
1970a7415d3SAndreas Gohr        global $ID;
1980a7415d3SAndreas Gohr        global $lang;
1990a7415d3SAndreas Gohr        global $conf;
2007053cd66SAndreas Gohr        global $ACT;
2017053cd66SAndreas Gohr        // redirect away from start page?
2027053cd66SAndreas Gohr        if($this->conf['redirectstart'] && $ID == $conf['start'] && $ACT == 'show'){
2037053cd66SAndreas Gohr            $lc = $this->hlp->getBrowserLang();
2047053cd66SAndreas Gohr            if(!$lc) $lc = $conf['lang'];
2057053cd66SAndreas Gohr            header('Location: '.wl($lc.':'.$conf['start'],'',true,'&'));
2067053cd66SAndreas Gohr            exit;
2077053cd66SAndreas Gohr        }
2080a7415d3SAndreas Gohr
2090a7415d3SAndreas Gohr        // check if we are in a foreign language namespace
210af1904f9SAndreas Gohr        $lc = $this->hlp->getLangPart($ID);
211a526927fSAndreas Gohr
212f2279247SAndreas Gohr        // store language in session (for page related views only)
213f2279247SAndreas Gohr        if(in_array($ACT,array('show','recent','diff','edit','preview','source','subscribe'))){
214f2279247SAndreas Gohr            $_SESSION[DOKU_COOKIE]['translationlc'] = $lc;
215f2279247SAndreas Gohr        }
216a526927fSAndreas Gohr        if(!$lc) $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
217a526927fSAndreas Gohr        if(!$lc) return;
21834591120SDominik Eckelmann        $this->locale = $lc;
21934591120SDominik Eckelmann
22034591120SDominik Eckelmann        if (!$this->getConf('translateui')) {
22134591120SDominik Eckelmann            return true;
22234591120SDominik Eckelmann        }
2230a7415d3SAndreas Gohr
2240a7415d3SAndreas Gohr        if(file_exists(DOKU_INC.'inc/lang/'.$lc.'/lang.php')) {
2250a7415d3SAndreas Gohr          require(DOKU_INC.'inc/lang/'.$lc.'/lang.php');
2260a7415d3SAndreas Gohr        }
2270a7415d3SAndreas Gohr        $conf['lang_before_translation'] = $conf['lang']; //store for later access in syntax plugin
2280a7415d3SAndreas Gohr        $conf['lang'] = $lc;
2290a7415d3SAndreas Gohr
2300a7415d3SAndreas Gohr        return true;
2310a7415d3SAndreas Gohr    }
232af1904f9SAndreas Gohr
233af1904f9SAndreas Gohr    /**
234*bbe70520SAndreas Gohr     * Hook Callback.  Resort page match results so that results are ordered by translation, having the
235af1904f9SAndreas Gohr     * default language first
236af1904f9SAndreas Gohr     */
237af1904f9SAndreas Gohr    function translation_search(&$event, $args) {
238d75e50bcSAndreas Gohr
239d75e50bcSAndreas Gohr        if($event->data['has_titles']){
240d75e50bcSAndreas Gohr            // sort into translation slots
241d75e50bcSAndreas Gohr            $res = array();
242d75e50bcSAndreas Gohr            foreach($event->result as $r => $t){
243d75e50bcSAndreas Gohr                $tr = $this->hlp->getLangPart($r);
244d75e50bcSAndreas Gohr                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
245d75e50bcSAndreas Gohr                $res["x$tr"][] = array($r,$t);
246d75e50bcSAndreas Gohr            }
247d75e50bcSAndreas Gohr            // sort by translations
248d75e50bcSAndreas Gohr            ksort($res);
249d75e50bcSAndreas Gohr            // combine
250d75e50bcSAndreas Gohr            $event->result = array();
251d75e50bcSAndreas Gohr            foreach($res as $r){
252d75e50bcSAndreas Gohr                foreach($r as $l){
253d75e50bcSAndreas Gohr                    $event->result[$l[0]] = $l[1];
254d75e50bcSAndreas Gohr                }
255d75e50bcSAndreas Gohr            }
256d75e50bcSAndreas Gohr        }else{
257d75e50bcSAndreas Gohr            # legacy support for old DokuWiki hooks
258d75e50bcSAndreas Gohr
259af1904f9SAndreas Gohr            // sort into translation slots
260af1904f9SAndreas Gohr            $res = array();
261af1904f9SAndreas Gohr            foreach($event->result as $r){
262af1904f9SAndreas Gohr                $tr = $this->hlp->getLangPart($r);
263af1904f9SAndreas Gohr                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
264af1904f9SAndreas Gohr                $res["x$tr"][] = $r;
265af1904f9SAndreas Gohr            }
266af1904f9SAndreas Gohr            // sort by translations
267af1904f9SAndreas Gohr            ksort($res);
268af1904f9SAndreas Gohr            // combine
269af1904f9SAndreas Gohr            $event->result = array();
270af1904f9SAndreas Gohr            foreach($res as $r){
271af1904f9SAndreas Gohr                $event->result = array_merge($event->result,$r);
272af1904f9SAndreas Gohr            }
273af1904f9SAndreas Gohr        }
274d75e50bcSAndreas Gohr    }
275af1904f9SAndreas Gohr
2760a7415d3SAndreas Gohr}
2770a7415d3SAndreas Gohr
278ec6cbde6SDominik Eckelmann//Setup VIM: ex: et ts=4 :
279