summaryrefslogtreecommitdiff
path: root/platform/www/lib/plugins/translation/action.php
blob: 6c79a709d0879dc0ccdd9bb63905f21e60bb9a34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
<?php
/**
 * Translation Plugin: Simple multilanguage plugin
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Andreas Gohr <andi@splitbrain.org>
 * @author     Guy Brand <gb@isis.u-strasbg.fr>
 */

// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();

/**
 * Class action_plugin_translation
 */
class action_plugin_translation extends DokuWiki_Action_Plugin {

    /**
     * For the helper plugin
     * @var helper_plugin_translation
     */
    var $helper = null;

    var $locale;

    /**
     * Constructor. Load helper plugin
     */
    function __construct() {
        $this->helper = plugin_load('helper', 'translation');
    }

    /**
     * Registers a callback function for a given event
     *
     * @param Doku_Event_Handler $controller
     */
    function register(Doku_Event_Handler $controller) {
        $scriptName = basename($_SERVER['PHP_SELF']);

        // should the lang be applied to UI?
        if($this->getConf('translateui')) {
            switch($scriptName) {
                case 'js.php':
                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translation_js');
                    $controller->register_hook('JS_CACHE_USE', 'BEFORE', $this, 'translation_jscache');
                    break;

                case 'ajax.php':
                    $controller->register_hook('INIT_LANG_LOAD', 'BEFORE', $this, 'translate_media_manager');
                    break;

                case 'mediamanager.php':
                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
                    break;

                default:
                    $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'setJsCacheKey');
            }
        }

        if($scriptName !== 'js.php' && $scriptName !== 'ajax.php') {
            $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'translation_hook');
            $controller->register_hook('DETAIL_STARTED', 'BEFORE', $this, 'translation_hook');
            $controller->register_hook('MEDIAMANAGER_STARTED', 'BEFORE', $this, 'translation_hook');
        }

        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'translation_search');
        $controller->register_hook('COMMON_PAGETPL_LOAD', 'AFTER', $this, 'page_template_replacement');
    }

    /**
     * Hook Callback. Make current language available as page template placeholder and handle
     * original language copying
     *
     * @param Doku_Event $event
     * @param $args
     */
    function page_template_replacement(Doku_Event $event, $args) {
        global $ID;

        // load orginal content as template?
        if($this->getConf('copytrans') && $this->helper->istranslatable($ID, false)) {
            // look for existing translations
            $translations = $this->helper->getAvailableTranslations($ID);
            if($translations) {
                // find original language (might've been provided via parameter or use first translation)
                $orig = (string) $_REQUEST['fromlang'];
                if(!$orig) $orig = array_shift(array_keys($translations));

                // load file
                $origfile = $translations[$orig];
                $event->data['tpl'] = io_readFile(wikiFN($origfile));

                // prefix with warning
                $warn = io_readFile($this->localFN('totranslate'));
                if($warn) $warn .= "\n\n";
                $event->data['tpl'] = $warn . $event->data['tpl'];

                // show user a choice of translations if any
                if(count($translations) > 1) {
                    $links = array();
                    foreach($translations as $t => $l) {
                        $links[] = '<a href="' . wl($ID, array('do' => 'edit', 'fromlang' => $t)) . '">' . $this->helper->getLocalName($t) . '</a>';
                    }

                    msg(
                        sprintf(
                            $this->getLang('transloaded'),
                            $this->helper->getLocalName($orig),
                            join(', ', $links)
                        )
                    );
                }

            }
        }

        // apply placeholders
        $event->data['tpl'] = str_replace('@LANG@', $this->helper->realLC(''), $event->data['tpl']);
        $event->data['tpl'] = str_replace('@TRANS@', $this->helper->getLangPart($ID), $event->data['tpl']);
    }

    /**
     * Hook Callback. Load correct translation when loading JavaScript
     *
     * @param Doku_Event $event
     * @param $args
     */
    function translation_js(Doku_Event $event, $args) {
        global $conf;
        if(!isset($_GET['lang'])) return;
        if(!in_array($_GET['lang'], $this->helper->translations)) return;
        $lang = $_GET['lang'];
        $event->data = $lang;
        $conf['lang'] = $lang;
    }

    /**
     * Hook Callback. Pass language code to JavaScript dispatcher
     *
     * @param Doku_Event $event
     * @param $args
     * @return bool
     */
    function setJsCacheKey(Doku_Event $event, $args) {
        if(!isset($this->locale)) return false;
        $count = count($event->data['script']);
        for($i = 0; $i < $count; $i++) {
            if(strpos($event->data['script'][$i]['src'], '/lib/exe/js.php') !== false) {
                $event->data['script'][$i]['src'] .= '&lang=' . hsc($this->locale);
            }
        }

        return false;
    }

    /**
     * Hook Callback. Make sure the JavaScript is translation dependent
     *
     * @param Doku_Event $event
     * @param $args
     */
    function translation_jscache(Doku_Event $event, $args) {
        if(!isset($_GET['lang'])) return;
        if(!in_array($_GET['lang'], $this->helper->translations)) return;

        $lang = $_GET['lang'];
        // reuse the constructor to reinitialize the cache key
        if(method_exists($event->data, '__construct')) {
            // New PHP 5 style constructor
            $event->data->__construct(
                $event->data->key . $lang,
                $event->data->ext
            );
        } else {
            // Old PHP 4 style constructor - deprecated
            $event->data->cache(
                $event->data->key . $lang,
                $event->data->ext
            );
        }
    }

    /**
     * Hook Callback. Translate the AJAX loaded media manager
     *
     * @param Doku_Event $event
     * @param $args
     */
    function translate_media_manager(Doku_Event $event, $args) {
        global $conf;
        if(isset($_REQUEST['ID'])) {
            $id = getID();
            $lc = $this->helper->getLangPart($id);
        } elseif(isset($_SESSION[DOKU_COOKIE]['translationlc'])) {
            $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
        } else {
            return;
        }
        if(!$lc) return;

        $conf['lang'] = $lc;
        $event->data = $lc;
    }

    /**
     * Hook Callback. Change the UI language in foreign language namespaces
     *
     * @param Doku_Event $event
     * @param $args
     * @return bool
     */
    function translation_hook(Doku_Event $event, $args) {
        global $ID;
        /** @noinspection PhpUnusedLocalVariableInspection we include the language file later on */
        global $lang;
        global $conf;
        global $ACT;
        // redirect away from start page?
        if($this->getConf('redirectstart') && $ID == $conf['start'] && $ACT == 'show') {
            $lc = $this->helper->getBrowserLang();

            list($translatedStartpage,) = $this->helper->buildTransID($lc, $conf['start']);
            if (cleanID($translatedStartpage) !== cleanID($ID)) {
                send_redirect(wl($translatedStartpage, '', true));
            }
        }

        // check if we are in a foreign language namespace
        $lc = $this->helper->getLangPart($ID);

        // store language in session (for page related views only)
        if(in_array($ACT, array('show', 'recent', 'diff', 'edit', 'preview', 'source', 'subscribe'))) {
            $_SESSION[DOKU_COOKIE]['translationlc'] = $lc;
        }
        if(!$lc) $lc = $_SESSION[DOKU_COOKIE]['translationlc'];
        if(!$lc) return false;
        $this->locale = $lc;

        if(!$this->getConf('translateui')) {
            return true;
        }

        if(file_exists(DOKU_INC . 'inc/lang/' . $lc . '/lang.php')) {
            require(DOKU_INC . 'inc/lang/' . $lc . '/lang.php');
        }
        $conf['lang_before_translation'] = $conf['lang']; //store for later access in syntax plugin
        $conf['lang'] = $lc;

        return true;
    }

    /**
     * Hook Callback.  Resort page match results so that results are ordered by translation, having the
     * default language first
     *
     * @param Doku_Event $event
     * @param $args
     */
    function translation_search(Doku_Event $event, $args) {

        if($event->data['has_titles']) {
            // sort into translation slots
            $res = array();
            foreach($event->result as $r => $t) {
                $tr = $this->helper->getLangPart($r);
                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
                $res["x$tr"][] = array($r, $t);
            }
            // sort by translations
            ksort($res);
            // combine
            $event->result = array();
            foreach($res as $r) {
                foreach($r as $l) {
                    $event->result[$l[0]] = $l[1];
                }
            }
        } else {
            # legacy support for old DokuWiki hooks

            // sort into translation slots
            $res = array();
            foreach($event->result as $r) {
                $tr = $this->helper->getLangPart($r);
                if(!is_array($res["x$tr"])) $res["x$tr"] = array();
                $res["x$tr"][] = $r;
            }
            // sort by translations
            ksort($res);
            // combine
            $event->result = array();
            foreach($res as $r) {
                $event->result = array_merge($event->result, $r);
            }
        }
    }

}

//Setup VIM: ex: et ts=4 :