xref: /plugin/autotranslation/action.php (revision ba82fb969f0c6e38db7f39e31eb5981654a41e64)
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    /**
19c54240efSGuillaume Turri     * For the helper plugin
20cabcc95dSDominik Eckelmann     * @var helper_plugin_translation
21af1904f9SAndreas Gohr     */
22c54240efSGuillaume Turri    var $helper = 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() {
30c54240efSGuillaume Turri        $this->helper =& plugin_load('helper', 'translation');
31af1904f9SAndreas Gohr    }
32af1904f9SAndreas Gohr
33af1904f9SAndreas Gohr    /**
34c54240efSGuillaume Turri     * Register the events
350a7415d3SAndreas Gohr     */
360a7415d3SAndreas Gohr    function register(&$controller) {
37ec6cbde6SDominik Eckelmann        $scriptName = basename($_SERVER['PHP_SELF']);
38e5e7e41dSAndreas Gohr
39c54240efSGuillaume Turri        // should the lang be applied to UI?
4034591120SDominik Eckelmann        if($this->getConf('translateui')) {
41ec6cbde6SDominik Eckelmann            switch($scriptName) {
42ec6cbde6SDominik Eckelmann                case 'js.php':
43ec6cbde6SDominik Eckelmann                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translation_js');
44db7c51b4SAndreas Gohr                    $controller->register_hook('JS_CACHE_USE', 'BEFORE', $this, 'translation_jscache');
45ec6cbde6SDominik Eckelmann                    break;
46ec6cbde6SDominik Eckelmann
47ec6cbde6SDominik Eckelmann                case 'ajax.php':
48ec6cbde6SDominik Eckelmann                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translate_media_manager');
49ec6cbde6SDominik Eckelmann                    break;
50ec6cbde6SDominik Eckelmann
51ec6cbde6SDominik Eckelmann                case 'mediamanager.php':
52ec6cbde6SDominik Eckelmann                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
53ec6cbde6SDominik Eckelmann                    break;
54ec6cbde6SDominik Eckelmann
55ec6cbde6SDominik Eckelmann                default:
56ec6cbde6SDominik Eckelmann                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
57ec6cbde6SDominik Eckelmann            }
580a7415d3SAndreas Gohr        }
5934591120SDominik Eckelmann
6034591120SDominik Eckelmann        if($scriptName !== 'js.php' && $scriptName !== 'ajax.php') {
6134591120SDominik Eckelmann            $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'translation_hook');
6234591120SDominik Eckelmann            $controller->register_hook('MEDIAMANAGER_STARTED', 'BEFORE', $this, 'translation_hook');
6334591120SDominik Eckelmann        }
6434591120SDominik Eckelmann
65af1904f9SAndreas Gohr        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'translation_search');
66cabcc95dSDominik Eckelmann        $controller->register_hook('COMMON_PAGETPL_LOAD', 'AFTER', $this, 'page_template_replacement');
67cabcc95dSDominik Eckelmann    }
68cabcc95dSDominik Eckelmann
69bbe70520SAndreas Gohr    /**
70bbe70520SAndreas Gohr     * Hook Callback. Make current language available as page template placeholder and handle
71bbe70520SAndreas Gohr     * original language copying
72bbe70520SAndreas Gohr     *
73bbe70520SAndreas Gohr     * @param $event
74bbe70520SAndreas Gohr     * @param $args
75bbe70520SAndreas Gohr     */
76cabcc95dSDominik Eckelmann    function page_template_replacement(&$event, $args) {
77cabcc95dSDominik Eckelmann        global $ID;
78bbe70520SAndreas Gohr
79bbe70520SAndreas Gohr        // load orginal content as template?
80c54240efSGuillaume Turri        if($this->getConf('copytrans') && $this->helper->istranslatable($ID, false)) {
81bbe70520SAndreas Gohr            // look for existing translations
82c54240efSGuillaume Turri            $translations = $this->helper->getAvailableTranslations($ID);
83bbe70520SAndreas Gohr            if($translations) {
84bbe70520SAndreas Gohr                // find original language (might've been provided via parameter or use first translation)
85bbe70520SAndreas Gohr                $orig = (string) $_REQUEST['fromlang'];
86bbe70520SAndreas Gohr                if(!$orig) $orig = array_shift(array_keys($translations));
87bbe70520SAndreas Gohr
88bbe70520SAndreas Gohr                // load file
89bbe70520SAndreas Gohr                $origfile = $translations[$orig];
90bbe70520SAndreas Gohr                $event->data['tpl'] = io_readFile(wikiFN($origfile));
91bbe70520SAndreas Gohr
92bbe70520SAndreas Gohr                // prefix with warning
93bbe70520SAndreas Gohr                $warn = io_readFile($this->localFN('totranslate'));
94bbe70520SAndreas Gohr                if($warn) $warn .= "\n\n";
95bbe70520SAndreas Gohr                $event->data['tpl'] = $warn . $event->data['tpl'];
96bbe70520SAndreas Gohr
97bbe70520SAndreas Gohr                // show user a choice of translations if any
98bbe70520SAndreas Gohr                if(count($translations) > 1) {
99bbe70520SAndreas Gohr                    $links = array();
100bbe70520SAndreas Gohr                    foreach($translations as $t => $l) {
101c54240efSGuillaume Turri                        $links[] = '<a href="' . wl($ID, array('do' => 'edit', 'fromlang' => $t)) . '">' . $this->helper->getLocalName($t) . '</a>';
102bbe70520SAndreas Gohr                    }
103bbe70520SAndreas Gohr
1045fd0d0d1SAndreas Gohr                    msg(
1055fd0d0d1SAndreas Gohr                        sprintf(
106bbe70520SAndreas Gohr                            $this->getLang('transloaded'),
107c54240efSGuillaume Turri                            $this->helper->getLocalName($orig),
108bbe70520SAndreas Gohr                            join(', ', $links)
109bbe70520SAndreas Gohr                        )
110bbe70520SAndreas Gohr                    );
111bbe70520SAndreas Gohr                }
112bbe70520SAndreas Gohr
113bbe70520SAndreas Gohr            }
114bbe70520SAndreas Gohr        }
115bbe70520SAndreas Gohr
116bbe70520SAndreas Gohr        // apply placeholders
117c54240efSGuillaume Turri        $event->data['tpl'] = str_replace('@LANG@', $this->helper->realLC(''), $event->data['tpl']);
118c54240efSGuillaume Turri        $event->data['tpl'] = str_replace('@TRANS@', $this->helper->getLangPart($ID), $event->data['tpl']);
1190a7415d3SAndreas Gohr    }
1200a7415d3SAndreas Gohr
121bbe70520SAndreas Gohr    /**
122bbe70520SAndreas Gohr     * Hook Callback. Load correct translation when loading JavaScript
123bbe70520SAndreas Gohr     *
124bbe70520SAndreas Gohr     * @param $event
125bbe70520SAndreas Gohr     * @param $args
126bbe70520SAndreas Gohr     */
127bbe70520SAndreas Gohr    function translation_js(&$event, $args) {
128bbe70520SAndreas Gohr        global $conf;
129bbe70520SAndreas Gohr        if(!isset($_GET['lang'])) return;
1305e1f71acSGuillaume Turri        if(!in_array($_GET['lang'], $this->helper->translations)) return;
131bbe70520SAndreas Gohr        $lang = $_GET['lang'];
132bbe70520SAndreas Gohr        $event->data = $lang;
133bbe70520SAndreas Gohr        $conf['lang'] = $lang;
134bbe70520SAndreas Gohr    }
135bbe70520SAndreas Gohr
136bbe70520SAndreas Gohr    /**
137bbe70520SAndreas Gohr     * Hook Callback. Pass language code to JavaScript dispatcher
138bbe70520SAndreas Gohr     *
139bbe70520SAndreas Gohr     * @param $event
140bbe70520SAndreas Gohr     * @param $args
141bbe70520SAndreas Gohr     * @return bool
142bbe70520SAndreas 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
155bbe70520SAndreas Gohr    /**
156bbe70520SAndreas Gohr     * Hook Callback. Make sure the JavaScript is translation dependent
157bbe70520SAndreas Gohr     *
158bbe70520SAndreas Gohr     * @param $event
159bbe70520SAndreas Gohr     * @param $args
160bbe70520SAndreas Gohr     */
161db7c51b4SAndreas Gohr    function translation_jscache(&$event, $args) {
162db7c51b4SAndreas Gohr        if(!isset($_GET['lang'])) return;
1635e1f71acSGuillaume Turri        if(!in_array($_GET['lang'], $this->helper->translations)) return;
164db7c51b4SAndreas Gohr
165db7c51b4SAndreas Gohr        $lang = $_GET['lang'];
166db7c51b4SAndreas Gohr        // reuse the constructor to reinitialize the cache key
167*ba82fb96SAndreas Gohr        if(method_exists($event->data, '__construct')) {
168*ba82fb96SAndreas Gohr            // New PHP 5 style constructor
16900e50232SAndreas Gohr            $event->data->__construct(
170db7c51b4SAndreas Gohr                $event->data->key . $lang,
171db7c51b4SAndreas Gohr                $event->data->ext
172db7c51b4SAndreas Gohr            );
173*ba82fb96SAndreas Gohr        } else {
174*ba82fb96SAndreas Gohr            // Old PHP 4 style constructor - deprecated
175*ba82fb96SAndreas Gohr            $event->data->cache(
176*ba82fb96SAndreas Gohr                $event->data->key . $lang,
177*ba82fb96SAndreas Gohr                $event->data->ext
178*ba82fb96SAndreas Gohr            );
179*ba82fb96SAndreas Gohr        }
180ec6cbde6SDominik Eckelmann    }
181ec6cbde6SDominik Eckelmann
182bbe70520SAndreas Gohr    /**
183bbe70520SAndreas Gohr     * Hook Callback. Translate the AJAX loaded media manager
184bbe70520SAndreas Gohr     *
185bbe70520SAndreas Gohr     * @param $event
186bbe70520SAndreas Gohr     * @param $args
187bbe70520SAndreas Gohr     */
188ec6cbde6SDominik Eckelmann    function translate_media_manager(&$event, $args) {
189ec6cbde6SDominik Eckelmann        global $conf;
190ec6cbde6SDominik Eckelmann        if(isset($_REQUEST['ID'])) {
191ec6cbde6SDominik Eckelmann            $id = getID();
192c54240efSGuillaume Turri            $lc = $this->helper->getLangPart($id);
193ec6cbde6SDominik Eckelmann        } elseif(isset($_SESSION[DOKU_COOKIE]['translationlc'])) {
194ec6cbde6SDominik Eckelmann            $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
195ec6cbde6SDominik Eckelmann        } else {
196db7c51b4SAndreas Gohr            return;
197ec6cbde6SDominik Eckelmann        }
198e5e7e41dSAndreas Gohr        if(!$lc) return;
199e5e7e41dSAndreas Gohr
200ec6cbde6SDominik Eckelmann        $conf['lang'] = $lc;
201ec6cbde6SDominik Eckelmann        $event->data = $lc;
202ec6cbde6SDominik Eckelmann    }
203ec6cbde6SDominik Eckelmann
2040a7415d3SAndreas Gohr    /**
205bbe70520SAndreas Gohr     * Hook Callback. Change the UI language in foreign language namespaces
2060a7415d3SAndreas Gohr     */
2070a7415d3SAndreas Gohr    function translation_hook(&$event, $args) {
2080a7415d3SAndreas Gohr        global $ID;
2090a7415d3SAndreas Gohr        global $lang;
2100a7415d3SAndreas Gohr        global $conf;
2117053cd66SAndreas Gohr        global $ACT;
2127053cd66SAndreas Gohr        // redirect away from start page?
2137053cd66SAndreas Gohr        if($this->conf['redirectstart'] && $ID == $conf['start'] && $ACT == 'show') {
214c54240efSGuillaume Turri            $lc = $this->helper->getBrowserLang();
2157053cd66SAndreas Gohr            if(!$lc) $lc = $conf['lang'];
2167053cd66SAndreas Gohr            header('Location: ' . wl($lc . ':' . $conf['start'], '', true, '&'));
2177053cd66SAndreas Gohr            exit;
2187053cd66SAndreas Gohr        }
2190a7415d3SAndreas Gohr
2200a7415d3SAndreas Gohr        // check if we are in a foreign language namespace
221c54240efSGuillaume Turri        $lc = $this->helper->getLangPart($ID);
222a526927fSAndreas Gohr
223f2279247SAndreas Gohr        // store language in session (for page related views only)
224f2279247SAndreas Gohr        if(in_array($ACT, array('show', 'recent', 'diff', 'edit', 'preview', 'source', 'subscribe'))) {
225f2279247SAndreas Gohr            $_SESSION[DOKU_COOKIE]['translationlc'] = $lc;
226f2279247SAndreas Gohr        }
227a526927fSAndreas Gohr        if(!$lc) $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
228a526927fSAndreas Gohr        if(!$lc) return;
22934591120SDominik Eckelmann        $this->locale = $lc;
23034591120SDominik Eckelmann
23134591120SDominik Eckelmann        if(!$this->getConf('translateui')) {
23234591120SDominik Eckelmann            return true;
23334591120SDominik Eckelmann        }
2340a7415d3SAndreas Gohr
2350a7415d3SAndreas Gohr        if(file_exists(DOKU_INC . 'inc/lang/' . $lc . '/lang.php')) {
2360a7415d3SAndreas Gohr            require(DOKU_INC . 'inc/lang/' . $lc . '/lang.php');
2370a7415d3SAndreas Gohr        }
2380a7415d3SAndreas Gohr        $conf['lang_before_translation'] = $conf['lang']; //store for later access in syntax plugin
2390a7415d3SAndreas Gohr        $conf['lang'] = $lc;
2400a7415d3SAndreas Gohr
2410a7415d3SAndreas Gohr        return true;
2420a7415d3SAndreas Gohr    }
243af1904f9SAndreas Gohr
244af1904f9SAndreas Gohr    /**
245bbe70520SAndreas Gohr     * Hook Callback.  Resort page match results so that results are ordered by translation, having the
246af1904f9SAndreas Gohr     * default language first
247af1904f9SAndreas Gohr     */
248af1904f9SAndreas Gohr    function translation_search(&$event, $args) {
249d75e50bcSAndreas Gohr
250d75e50bcSAndreas Gohr        if($event->data['has_titles']) {
251d75e50bcSAndreas Gohr            // sort into translation slots
252d75e50bcSAndreas Gohr            $res = array();
253d75e50bcSAndreas Gohr            foreach($event->result as $r => $t) {
254c54240efSGuillaume Turri                $tr = $this->helper->getLangPart($r);
255d75e50bcSAndreas Gohr                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
256d75e50bcSAndreas Gohr                $res["x$tr"][] = array($r, $t);
257d75e50bcSAndreas Gohr            }
258d75e50bcSAndreas Gohr            // sort by translations
259d75e50bcSAndreas Gohr            ksort($res);
260d75e50bcSAndreas Gohr            // combine
261d75e50bcSAndreas Gohr            $event->result = array();
262d75e50bcSAndreas Gohr            foreach($res as $r) {
263d75e50bcSAndreas Gohr                foreach($r as $l) {
264d75e50bcSAndreas Gohr                    $event->result[$l[0]] = $l[1];
265d75e50bcSAndreas Gohr                }
266d75e50bcSAndreas Gohr            }
267d75e50bcSAndreas Gohr        } else {
268d75e50bcSAndreas Gohr            # legacy support for old DokuWiki hooks
269d75e50bcSAndreas Gohr
270af1904f9SAndreas Gohr            // sort into translation slots
271af1904f9SAndreas Gohr            $res = array();
272af1904f9SAndreas Gohr            foreach($event->result as $r) {
273c54240efSGuillaume Turri                $tr = $this->helper->getLangPart($r);
274af1904f9SAndreas Gohr                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
275af1904f9SAndreas Gohr                $res["x$tr"][] = $r;
276af1904f9SAndreas Gohr            }
277af1904f9SAndreas Gohr            // sort by translations
278af1904f9SAndreas Gohr            ksort($res);
279af1904f9SAndreas Gohr            // combine
280af1904f9SAndreas Gohr            $event->result = array();
281af1904f9SAndreas Gohr            foreach($res as $r) {
282af1904f9SAndreas Gohr                $event->result = array_merge($event->result, $r);
283af1904f9SAndreas Gohr            }
284af1904f9SAndreas Gohr        }
285d75e50bcSAndreas Gohr    }
286af1904f9SAndreas Gohr
2870a7415d3SAndreas Gohr}
2880a7415d3SAndreas Gohr
289ec6cbde6SDominik Eckelmann//Setup VIM: ex: et ts=4 :
290