]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/_WikiTranslation.php
Update lib/nusoap/nusoap.php to version 0.9.5
[SourceForge/phpwiki.git] / lib / plugin / _WikiTranslation.php
1 <?php
2
3 /*
4  * Copyright 2004,2005 $ThePhpWikiProgrammingTeam
5  *
6  * This file is part of PhpWiki.
7  *
8  * PhpWiki is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * PhpWiki is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 /**
24  * _WikiTranslation:  Display pagenames and other strings in various languages.
25  * Can also be used to let a favorite translation service translate a whole page.
26  * Current favorite: translate.google.com if from_lang = en or fr
27  *
28  * Examples:
29  *  <<_WikiTranslation page=HomePage languages=fr >>
30  *     Translation service for HomePage into french (redirect to translate.google.com)
31  *  <<_WikiTranslation what=pages >>
32  *     Translation matrix of all pages with proper translations (all in pgsrc)
33  *  <<_WikiTranslation what=wikiwords match="W*" limit=20 >>
34  *     Translation matrix of the first 20 wikiwords matching "W*"
35  *  <<_WikiTranslation string=HomePage languages=fr,de,sv >>
36  *     Translation matrix for all given languages
37  *  <<_WikiTranslation string=HomePage >>
38  *     Translation matrix for all supported languages
39  *  <<_WikiTranslation string=HomePage languages=fr >>
40  *     Just return the translated string for this language.
41  *
42  * @author:  Reini Urban
43  */
44
45 /* Container for untranslated pagenames. Needed to show up in locale/po/phpwiki.pot */
46 $pgsrc_container =
47     _("AllPagesCreatedByMe") . ',' .
48         _("AllPagesLastEditedByMe") . ',' .
49         _("AllPagesOwnedByMe") . ',' .
50         _("BackLinks") . ',' .
51         _("CategoryCategory") . ',' .
52         _("CategoryHomePages") . ',' .
53         _("DebugInfo") . ',' .
54         _("EditMetaData") . ',' .
55         _("FindPage") . ',' .
56         _("FullRecentChanges") . ',' .
57         _("Help/AddingPages") . ',' .
58         _("Help/AddCommentPlugin") . ',' .
59         _("Help/AuthorHistoryPlugin") . ',' .
60         _("Help/CalendarListPlugin") . ',' .
61         _("Help/CalendarPlugin") . ',' .
62         _("Help/CommentPlugin") . ',' .
63         _("Help/CreateTocPlugin") . ',' .
64         _("Help/EditMetaDataPlugin") . ',' .
65         _("Help/ExternalSearchPlugin") . ',' .
66         _("Help/FoafViewerPlugin") . ',' .
67         _("Help/FrameIncludePlugin") . ',' .
68         _("Help/HelloWorldPlugin") . ',' .
69         _("Help/IncludePagePlugin") . ',' .
70         _("Help/LinkIcons") . ',' .
71         _("Help/MagicPhpWikiURLs") . ',' .
72         _("Help/MoreAboutMechanics") . ',' .
73         _("Help/OldStyleTablePlugin") . ',' .
74         _("Help/PhotoAlbumPlugin") . ',' .
75         _("Help/PhpHighlightPlugin") . ',' .
76         _("Help/PhpWeatherPlugin") . ',' .
77         _("Help/PhpWiki") . ',' .
78         _("Help/PloticusPlugin") . ',' .
79         _("Help/RawHtmlPlugin") . ',' .
80         _("Help/RedirectToPlugin") . ',' .
81         _("Help/RichTablePlugin") . ',' .
82         _("Help/SystemInfoPlugin") . ',' .
83         _("Help/TranscludePlugin") . ',' .
84         _("Help/UnfoldSubpagesPlugin") . ',' .
85         _("Help/UpLoadPlugin") . ',' .
86         _("Help/WabiSabi") . ',' .
87         _("Help/WikiBlogPlugin") . ',' .
88         _("Help/WikiPlugin") . ',' .
89         _("Help/WikiWikiWeb");
90 _("HomePageAlias") . ',' .
91     _("InterWiki") . ',' .
92 //  _("PageDump") .','.
93     _("PhpWikiAdministration/Chmod") . ',' .
94     _("PhpWikiAdministration/Chown") . ',' .
95     _("PhpWikiAdministration/Remove") . ',' .
96     _("PhpWikiAdministration/Rename") . ',' .
97     _("PhpWikiAdministration/Replace") . ',' .
98     _("PhpWikiAdministration/SetAcl") . ',' .
99     _("PhpWikiDocumentation") . ',' .
100     _("PhpWikiPoll") . ',' .
101     _("RecentVisitors") . ',' .
102     _("ReleaseNotes") . ',' .
103 //    _("SpellCheck") .','.
104     _("TranslateText") . ',' .
105     _("UpLoad") . ',' .
106
107     require_once 'lib/PageList.php';
108
109 class WikiPlugin__WikiTranslation
110     extends WikiPlugin
111 {
112
113     function getName()
114     {
115         return _("_WikiTranslation");
116     }
117
118     function getDescription()
119     {
120         return _("Show translations of various words or pages.");
121     }
122
123     function getDefaultArguments()
124     {
125         return array_merge
126         (
127             PageList::supportedArgs(),
128             array('languages' => '', // comma delimited string of de,en,sv,...
129                 'string' => '',
130                 'page' => '', // use a translation service
131                 'what' => 'pages', // or 'buttons', 'plugins' or 'wikiwords'
132
133                 'match' => '*',
134                 'from_lang' => false,
135                 'include_empty' => false,
136                 //'exclude'       => '',
137                 //'sortby'        => '',
138                 //'limit'         => 0,
139                 'nolinks' => false, // don't display any links
140                 // (for development only)
141                 'noT' => false // don't display the T link
142                 // (for development only)
143             ));
144     }
145
146     function init_locale($lang)
147     {
148         if ($lang != $this->lang)
149             update_locale($lang);
150         if ($lang == 'en') {
151             // Hack alert! we need hash for stepping through it, even if it's
152             // in the wrong language
153             include (FindFile("locale/de/LC_MESSAGES/phpwiki.php", 0, 'reinit'));
154             foreach ($locale as $en => $de) {
155                 $locale[$en] = $en;
156             }
157             // gettext module loaded: must load the LC_MESSAGES php hash
158         } elseif (function_exists('bindtextdomain')) {
159             include (FindFile("locale/$lang/LC_MESSAGES/phpwiki.php", 0, 'reinit'));
160             //include (FindLocalizedFile("LC_MESSAGES/phpwiki.php", 0,'reinit'));
161             // we already have a $locale, but maybe it's in the wrong language
162         } elseif ($lang != $this->lang or empty($GLOBALS['locale'])) {
163             include (FindFile("locale/$lang/LC_MESSAGES/phpwiki.php", 0, 'reinit'));
164         } else {
165             $locale = & $GLOBALS['locale'];
166         }
167         $this->_locales[$lang] = $locale;
168     }
169
170     // reverse translation:
171     function translate_to_en($text, $lang = false)
172     {
173         if (!$lang) $lang = $this->lang; // current locale
174         if ($lang == 'en') return $text;
175
176         $this->_locales = array();
177         $this->_reverse_locales = array();
178
179         if (!isset($this->_locales[$lang])) {
180             $this->init_locale($lang);
181         }
182         assert(!empty($this->_locales[$lang]));
183         if (!isset($this->_reverse_locales[$lang])) {
184             // and now do a reverse lookup in the $locale hash
185             $this->_reverse_locales[$lang] = array_flip($this->_locales[$lang]);
186         }
187         if (!empty($this->_reverse_locales[$lang][$text])) {
188             return $this->_reverse_locales[$lang][$text];
189         } else {
190             return $text;
191         }
192     }
193
194     /**
195      * setlocale() switching with the gettext extension is by far too slow.
196      * So use the hash regardless if gettext is loaded or not.
197      */
198     function fast_translate($text, $to_lang, $from_lang = false)
199     {
200         if (!$from_lang) $from_lang = $this->lang; // current locale
201         if ($from_lang == $to_lang) return $text;
202         // setup hash from en => to_lang
203         if (!isset($this->_locales[$to_lang]))
204             $this->init_locale($to_lang);
205         if ($from_lang != 'en') {
206             // get reverse gettext: translate to english
207             $text = $this->translate_to_en($text, $from_lang);
208         }
209         return !empty($this->_locales[$to_lang][$text])
210             ? $this->_locales[$to_lang][$text]
211             : $text;
212     }
213
214     //FIXME! There's something wrong.
215     function translate($text, $to_lang, $from_lang = false)
216     {
217         if (!$from_lang) $from_lang = $this->lang; // current locale
218         if ($from_lang == $to_lang) return $text;
219         // Speed up hash lookup. Not needed for gettext module
220         if (!isset($this->_locales[$from_lang]) and !function_exists('bindtextdomain')) {
221             $this->init_locale($from_lang);
222         }
223         if ($from_lang != 'en') {
224             // get reverse gettext: translate to english
225             $en = $this->translate_to_en($text, $from_lang);
226             // and then to target
227             update_locale($to_lang);
228             $result = gettext($en);
229             update_locale($from_lang);
230         } else {
231             // locale switching is very slow with the gettext extension.
232             // better use fast_translate
233             if ($from_lang != $to_lang) {
234                 update_locale($to_lang);
235             }
236             $result = gettext($text);
237             if ($from_lang != $to_lang) {
238                 update_locale($from_lang);
239             }
240         }
241         return $result;
242     }
243
244     function run($dbi, $argstr, &$request, $basepage)
245     {
246         $this->args = $this->getArgs($argstr, $request);
247         extract($this->args);
248         $this->request = &$request;
249         if (!$from_lang) $from_lang = $request->getPref('lang');
250         if (!$from_lang) $from_lang = $GLOBALS['LANG'];
251         $this->lang = $from_lang;
252
253         if (empty($languages)) {
254             $available_languages = listAvailableLanguages();
255             if ($from_lang == 'en') {
256                 // "en" is always the first.
257                 array_shift($available_languages);
258             }
259             // put from_lang to the very end.
260             if (in_array($from_lang, $available_languages))
261                 $languages = $available_languages;
262             else
263                 $languages = array_merge($available_languages, array($from_lang));
264         } elseif (strstr($languages, ',')) {
265             $languages = explode(',', $languages);
266         } else {
267             $languages = array($languages);
268         }
269         if (in_array('zh', $languages) or in_array('ja', $languages)) {
270
271             // If the current charset != utf-8 the text will not be displayed correctly.
272             // But here we cannot change the header anymore. So we can decide to ignore them,
273             // or display them with all the errors.
274             //FIXME: do iconv the ob
275             if ($GLOBALS['charset'] != 'utf-8' and !defined('NEED_ICONV_TO')) {
276                 define('NEED_ICONV_TO', 'utf-8');
277                 //either the extension or external
278                 //$GLOBALS['charset'] = 'utf-8';
279             }
280         }
281         $to_lang = $languages[0];
282         if (!empty($string) and count($languages) == 1) {
283             return $this->translate($string, $to_lang, $from_lang);
284         }
285         if (!empty($page)) {
286             $pagename = $page;
287             if ($dbi->isWikiPage($pagename)) {
288                 $url = '';
289                 // google can only translate from english and french
290                 if (in_array($from_lang, array('en', 'fr'))) {
291                     $url = "http://translate.google.com/translate";
292                     $url .= "?langpair=" . urlencode($from_lang . "|" . $to_lang);
293                     $url .= "&u=" . urlencode(WikiURL($pagename, false, true));
294                 }
295                 // redirect or transclude?
296                 if ($url) {
297                     return $request->redirect($url);
298                 }
299                 return HTML(fmt("TODO: Google can only translate from english and french. Find a translation service for %s to language %s",
300                     WikiURL($pagename, false, true),
301                     $to_lang));
302             } else {
303                 return $this->error(fmt("%s is empty.", $pagename));
304             }
305         }
306
307         $pagelist = new PageList('', $exclude, $this->args);
308         $pagelist->_columns[0]->_heading = "$from_lang";
309         foreach ($languages as $lang) {
310             if ($lang == $from_lang) continue;
311             $field = "custom:$lang";
312             $pagelist->addColumnObject(
313                 new _PageList_Column_customlang($field, $from_lang, $this));
314         }
315         if (!empty($string)) {
316             $pagelist->addPage($string);
317             return $pagelist;
318         }
319         switch ($what) {
320             case 'allpages':
321                 $pagelist->addPages($dbi->getAllPages($include_empty, $sortby,
322                     $limit, $exclude));
323                 break;
324             case 'pages':
325                 // not all pages, only the pgsrc pages
326                 if (!is_array($exclude))
327                     $exclude = $pagelist->explodePageList($exclude, false, $sortby,
328                         $limit, $exclude);
329                 $path = FindLocalizedFile(WIKI_PGSRC);
330                 $pgsrc = new fileSet($path);
331                 foreach ($pgsrc->getFiles($exclude, $sortby, $limit) as $pagename) {
332                     $pagename = urldecode($pagename);
333                     if (substr($pagename, -1, 1) == '~') continue;
334                     if (in_array($pagename, $exclude))
335                         continue; // exclude page.
336                     if ($match != '*' and !glob_match($match, $pagename))
337                         continue;
338                     $page_handle = $dbi->getPage($pagename);
339                     $pagelist->addPage($page_handle);
340                 }
341                 break;
342             case 'wikiwords':
343                 if (!isset($this->_locales[$from_lang])) {
344                     $this->init_locale($from_lang);
345                 }
346                 $locale = & $this->_locales[$from_lang];
347                 if (is_array($locale)) {
348                     $count = 0;
349                     foreach ($locale as $from => $to) {
350                         if ($match != '*' and !glob_match($match, $from))
351                             continue;
352                         if (isWikiWord($from)) {
353                             $count++;
354                             $pagelist->addPage($from);
355                             if ($limit and $count > $limit) break;
356                         }
357                     }
358                 }
359                 break;
360             // all Button texts, which need a localized .png
361             // where to get them from? templates/*.tmpl: Button()
362             // and WikiLink(?,'button')
363             // navbar links, actionpages, and admin requests
364             case 'buttons':
365                 $buttons = $GLOBALS['AllActionPages'];
366                 $fileset = new FileSet(FindFile("themes/MacOSX/buttons/en"),
367                     "*.png");
368                 foreach ($fileset->getFiles() as $file) {
369                     $b = urldecode(substr($file, 0, -4));
370                     if (!in_array($b, $buttons))
371                         $buttons[] = $b;
372                 }
373                 $count = 0;
374                 foreach ($buttons as $button) {
375                     $pagelist->addPage($button);
376                     if ($limit and ++$count > $limit) break;
377                 }
378                 break;
379         }
380         return $pagelist;
381     }
382 }
383
384 class _PageList_Column_customlang extends _PageList_Column
385 {
386     function _PageList_Column_customlang($field, $from_lang, $plugin)
387     {
388         $this->_field = $field;
389         $this->_from_lang = $from_lang;
390         $this->_plugin =& $plugin;
391         $this->_what = $plugin->args['what'];
392         $this->_noT = $plugin->args['noT'];
393         $this->_nolinks = $plugin->args['nolinks'];
394         $this->_iscustom = substr($field, 0, 7) == 'custom:';
395         if ($this->_iscustom)
396             $this->_field = substr($field, 7);
397         //$heading = $field;
398         $this->dbi = &$GLOBALS['request']->getDbh();
399         $this->_PageList_Column_base($this->_field);
400     }
401
402     function _getValue($page, &$revision_handle)
403     {
404         if (is_object($page)) $text = $page->getName();
405         else $text = $page;
406         $trans = $this->_plugin->fast_translate($text, $this->_field,
407             $this->_from_lang);
408         // how to markup untranslated words and not existing pages?
409         // untranslated: (TODO) link to translation editor
410         if ($trans == $text or // untranslated
411             (($this->_from_lang != 'en') and
412                 ($this->_field != 'en') and
413                     ($trans == $this->_plugin->fast_translate($text, 'en',
414                         $this->_from_lang))
415             )
416         ) {
417             global $WikiTheme;
418             $link = $WikiTheme->linkUnknownWikiWord($trans);
419             if (!($this->_noT or $this->_nolinks)
420                 and $this->dbi->isWikiPage($trans)
421             ) {
422                 $url = WikiURL($trans, array('action' => 'TranslateText',
423                     'lang' => $this->_field));
424                 $button = $WikiTheme->makeButton('T', $url);
425                 $button->addTooltip(sprintf(_("Define the translation for %s in %s"),
426                     $trans, $this->_field));
427                 $link = HTML::span($button);
428                 $link->setAttr('class', 'wikiunknown');
429                 $text = HTML::span($WikiTheme->maybeSplitWikiWord($trans));
430                 $text->setAttr('style', 'text-decoration:line-through');
431                 $link->pushContent($text);
432                 return $link;
433             } elseif (is_object($page))
434                 return ''; else // not existing: empty
435                 return '';
436         } elseif (is_object($page)) {
437             if (!$this->_nolinks)
438                 return WikiLink($trans, 'auto');
439             else
440                 return $trans;
441         } else {
442             return $trans;
443         }
444     }
445 }
446
447 // Local Variables:
448 // mode: php
449 // tab-width: 8
450 // c-basic-offset: 4
451 // c-hanging-comment-ender-p: nil
452 // indent-tabs-mode: nil
453 // End: