]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/_WikiTranslation.php
plugin->run consistency: request as reference, added basepage.
[SourceForge/phpwiki.git] / lib / plugin / _WikiTranslation.php
1 <?php // -*-php-*-
2 rcs_id('$Id: _WikiTranslation.php,v 1.14 2004-07-08 20:30:07 rurban Exp $');
3 /*
4  Copyright 2004 $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
19  along with PhpWiki; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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  *  <?plugin _WikiTranslation page=HomePage languages=fr ?>
30  *     Translation service for HomePage into french (redirect to translate.google.com)
31  *  <?plugin _WikiTranslation what=pages ?>
32  *     Translation matrix of all pages with proper translations (all in pgsrc)
33  *  <?plugin _WikiTranslation what=wikiwords match="W*" limit=20 ?>
34  *     Translation matrix of the first 20 wikiwords matching "W*"
35  *  <?plugin _WikiTranslation string=HomePage languages=fr,de,sv ?>
36  *     Translation matrix for all given languages
37  *  <?plugin _WikiTranslation string=HomePage ?>
38  *     Translation matrix for all supported languages
39  *  <?plugin _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     _("AddCommentPlugin")  .','.
48     _("AddingPages")  .','.
49     _("AllPagesCreatedByMe")  .','.
50     _("AllPagesLastEditedByMe")  .','.
51     _("AllPagesOwnedByMe")  .','.
52     _("AuthorHistoryPlugin") .','.
53     _("BackLinks") .','.
54     _("CalendarListPlugin") .','.
55     _("CalendarPlugin") .','.
56     _("CategoryCategory")  .','.
57     _("CategoryHomePages")  .','.
58     _("CommentPlugin")  .','.
59     _("CreateTocPlugin")  .','.
60     _("DebugInfo") .','.
61     _("EditMetaData") .','.
62     _("EditMetaDataPlugin") .','.
63     _("ExternalSearchPlugin") .','.
64     _("FindPage") .','.
65     _("FoafViewerPlugin") .','.
66     _("FrameIncludePlugin") .','.
67     _("FullRecentChanges") .','.
68     _("HelloWorldPlugin") .','.
69     _("HomePageAlias") .','.
70     _("IncludePagePlugin") .','.
71     _("InterWiki") .','.
72     _("LinkIcons") .','.
73     _("MagicPhpWikiURLs") .','.
74     _("MoreAboutMechanics") .','.
75     _("NewMarkupTestPage") .','.
76     _("OldMarkupTestPage") .','.
77     _("OldStyleTablePlugin") .','.
78 //  _("PageDump") .','.
79     _("PageGroupTest") .','.
80     _("PageGroupTest/Four") .','.
81     _("PageGroupTest/One") .','.
82     _("PageGroupTest/Three") .','.
83     _("PageGroupTest/Two") .','.
84     _("PgsrcTranslation") .','.
85     _("PhotoAlbumPlugin") .','.
86     _("PhpHighlightPlugin") .','.
87     _("PhpWeatherPlugin") .','.
88     _("PhpWiki") .','.
89     _("PhpWikiAdministration/Chmod") .','.
90     _("PhpWikiAdministration/Chown") .','.
91     _("PhpWikiAdministration/Remove") .','.
92     _("PhpWikiAdministration/Rename") .','.
93     _("PhpWikiAdministration/Replace") .','.
94     _("PhpWikiDocumentation") .','.
95     _("PhpWikiPoll") .','.
96     _("PloticusPlugin") .','.
97     _("RawHtmlPlugin") .','.
98     _("RecentVisitors") .','.
99     _("RedirectToPlugin") .','.
100     _("ReleaseNotes") .','.
101     _("RichTablePlugin") .','.
102     _("SteveWainstead") .','.
103     _("SystemInfoPlugin") .','.
104     _("TranscludePlugin") .','.
105     _("TranslateText") .','.
106     _("UnfoldSubpagesPlugin") .','.
107     _("UpLoad") .','.
108     _("UpLoadPlugin") .','.
109     _("WabiSabi") .','.
110     _("WikiBlogPlugin") .','.
111     _("WikiPlugin") .','.
112     _("WikiWikiWeb");
113  
114 require_once('lib/PageList.php');
115
116 class WikiPlugin__WikiTranslation
117 extends WikiPlugin
118 {
119
120     function getName() {
121         return _("_WikiTranslation");
122     }
123
124     function getDescription() {
125         return _("Show translations of various words or pages");
126     }
127
128     function getVersion() {
129         return preg_replace("/[Revision: $]/", '',
130                             "\$Revision: 1.14 $");
131     }
132
133     function getDefaultArguments() {
134         return 
135             array( 'languages'  => '',  // comma delimited string of de,en,sv,...
136                    'string'     => '',  
137                    'page'       => '',  // use a translation service
138                    'what'       => 'pages', // or 'buttons', 'plugins' or 'wikiwords'
139
140                    'match'         => '*',
141                    'from_lang'     => false,
142                    'include_empty' => false,
143                    'exclude'       => '',
144                    'sortby'        => '',
145                    'limit'         => 0,
146                    'nolinks'       => false,  // don't display any links (for development only)
147                    'noT'           => false,  // don't display the T link (for development only)
148                    'debug'         => false
149                  );
150     }
151
152     function init_locale($lang) {
153         if ($lang != $this->lang)
154             update_locale($lang);
155         if ($lang == 'en') {
156             //hack alert! we need hash for stepping through it, even if it's in the wrong language
157             include (FindFile("locale/de/LC_MESSAGES/phpwiki.php", 0,'reinit'));
158             foreach ($locale as $en => $de) {
159                 $locale[$en] = $en;
160             }
161         // gettext module loaded: must load the LC_MESSAGES php hash
162         } elseif (function_exists ('bindtextdomain')) {
163             include (FindLocalizedFile("LC_MESSAGES/phpwiki.php", 0,'reinit'));
164         // we already have a $locale, but maybe it's in the wrong language
165         } elseif ($lang != $this->lang or empty($GLOBALS['locale'])) {
166             include (FindFile("locale/$lang/LC_MESSAGES/phpwiki.php", 0,'reinit'));
167         } else {
168            $locale = & $GLOBALS['locale'];
169         }
170         $this->_locales[$lang] = $locale;
171     }
172
173     // reverse translation: 
174     function translate_to_en($text, $lang=false) {
175         if (!$lang) $lang = $this->lang; // current locale
176         if ($lang == 'en') return $text;
177
178         $this->_locales = array();
179         $this->_reverse_locales = array();
180
181         if (!isset($this->_locales[$lang])) {
182             $this->init_locale($lang);
183         }
184         assert(!empty($this->_locales[$lang]));
185         if (!isset($this->_reverse_locales[$lang])) {
186             // and now do a reverse lookup in the $locale hash
187             $this->_reverse_locales[$lang] = array_flip($this->_locales[$lang]);
188         }
189         if (!empty($this->_reverse_locales[$lang][$text])) {
190             return $this->_reverse_locales[$lang][$text];
191         } else {
192             return $text;
193         }
194     }
195
196     function translate($text, $to_lang, $from_lang=false) {
197         if (!$from_lang) $from_lang = $this->lang; // current locale
198         if ($from_lang == $to_lang) return $text;
199         // speed up hash lookup. not needed for gettext module
200         if (!isset($this->_locales[$from_lang]) and !function_exists('bindtextdomain')) {
201             $this->init_locale($from_lang);
202         }
203         if ($from_lang != 'en') {
204             // get reverse gettext: translate to english
205             $en = $this->translate_to_en($text,$from_lang);
206             // and then to target
207             update_locale($to_lang);
208             $result = gettext($en);
209             update_locale($from_lang);
210         } else {
211             if ($from_lang != $to_lang) {
212                 update_locale($to_lang);
213             }
214             $result = gettext($text);
215             if ($from_lang != $to_lang) {
216                 update_locale($from_lang);
217             }
218         }
219         return $result;
220     }
221                 
222     function run($dbi, $argstr, &$request, $basepage) {
223         $this->args = $this->getArgs($argstr, $request);
224         extract($this->args);
225         $this->request = &$request;
226         if (!$from_lang) $from_lang = $request->getPref('lang');
227         if (!$from_lang) $from_lang = $GLOBALS['LANG'];
228         $this->lang = $from_lang;
229
230         if (empty($languages)) {
231             $available_languages = listAvailableLanguages();
232             if ($from_lang == 'en') {
233                 // "en" is always the first.
234                 array_shift($available_languages);
235             }
236             // put from_lang to the very end.
237             if (in_array($from_lang, $available_languages))
238                 $languages = $available_languages;
239             else
240                 $languages = array_merge($available_languages, array($from_lang));
241         } elseif (strstr($languages,',')) {
242             $languages = explode(',', $languages);
243         } else {
244             $languages = array($languages);
245         }
246         if (in_array('zh',$languages) or in_array('ja',$languages)) {
247             // if the current charset != utf-8 the text will not be displayed correctly
248             // but here we cannot change the header anymore. so we can decide to ignore them, 
249             // or display them with all the errors.
250             $GLOBALS['charset'] = 'utf-8';
251         }
252         $to_lang = $languages[0];
253         if (!empty($string) and count($languages)==1) {
254             return $this->translate($string, $to_lang, $from_lang);
255         }
256         if (!empty($page)) {
257             $pagename = $page;
258             if ($dbi->isWikiPage($pagename)) {
259                 $url = '';
260                 // google can only translate from english and french
261                 if (in_array($from_lang,array('en','fr'))) {
262                     $url = "http://translate.google.com/translate";
263                     $url .= "?langpair=" . urlencode($from_lang."|".$to_lang);
264                     $url .= "&u=" . urlencode(WikiURL($pagename, false, true));
265                 }
266                 // redirect or transclude?
267                 if ($url)
268                     return $request->redirect($url);
269                 return HTML(fmt("TODO: Google can only translate from english and french. Find a translation service for %s to language %s",
270                                 WikiURL($pagename, false, true),
271                                 $to_lang));
272             } else
273                 return $this->error(fmt("%s is empty",$pagename));
274         }
275         
276         $pagelist = new PageList('', $exclude, $this->args);
277         $pagelist->_columns[0]->_heading = "$from_lang";
278         foreach ($languages as $lang) {
279             if ($lang == $from_lang) continue;
280             $field = "custom:$lang";
281             $pagelist->addColumnObject(new _PageList_Column_customlang($field, $from_lang, $this));
282         }
283         if (!empty($string)) {
284             $pagelist->addPage( $string );
285             return $pagelist;
286         }
287         switch ($what) {
288         case 'allpages':
289             $pagelist->addPages( $dbi->getAllPages($include_empty, $sortby, $limit) );
290             break;
291         case 'pages':
292             // not all pages, only the pgsrc pages
293             if (!is_array($exclude))
294                 $exclude = $pagelist->explodePageList($exclude, false, $sortby, $limit);
295             $path = FindLocalizedFile(WIKI_PGSRC);
296             $pgsrc = new fileSet($path);
297             foreach ($pgsrc->getFiles($exclude, $sortby, $limit) as $pagename) {
298                 $pagename = urldecode($pagename);
299                 if (substr($pagename,-1,1) == '~') continue;
300                 if (in_array($pagename, $exclude))
301                     continue;             // exclude page.
302                 if ($match != '*' and !glob_match($match, $pagename))
303                     continue;
304                 $page_handle = $dbi->getPage($pagename);
305                 $pagelist->addPage( $page_handle );
306             }
307             break;
308         case 'wikiwords':
309             if (!isset($this->_locales[$from_lang])) {
310                 $this->init_locale($from_lang);
311             }
312             $locale = & $this->_locales[$from_lang];
313             if (is_array($locale)) {
314                 $count = 0;
315                 foreach ($locale as $from => $to) {
316                     if ($match != '*' and !glob_match($match, $from))
317                         continue;
318                     if (isWikiWord($from)) {
319                         $count++;
320                         $pagelist->addPage( $from );
321                         if ($limit and $count > $limit) break;
322                     }
323                 }
324             }
325             break;
326         // all Button texts, which need a localized .png
327         // where to get them from? templates/*.tmpl: Button() and WikiLink(?,'button')
328         // navbar links, actionpages, and admin requests
329         case 'buttons':
330             $buttons = $GLOBALS['AllActionPages'];
331             $fileset = new FileSet(FindFile("themes/MacOSX/buttons/en"), "*.png");
332             foreach ($fileset->getFiles() as $file) {
333                 $b = urldecode(substr($file, 0, -4));
334                 if (!in_array($b,$buttons))
335                     $buttons[] = $b;
336             }
337             $count = 0;
338             foreach ($buttons as $button) {
339                 $pagelist->addPage( $button );
340                 if ($limit and ++$count > $limit) break;
341             }
342             break;
343         }
344         return $pagelist;
345     }
346 };
347
348 class _PageList_Column_customlang extends _PageList_Column {
349     function _PageList_Column_customlang($field, $from_lang, $plugin) {
350         $this->_field = $field;
351         $this->_from_lang = $from_lang;
352         $this->_plugin =& $plugin;
353         $this->_what = $plugin->args['what'];
354         $this->_noT = $plugin->args['noT'];
355         $this->_nolinks = $plugin->args['nolinks'];
356         $this->_iscustom = substr($field, 0, 7) == 'custom:';
357         if ($this->_iscustom)
358             $this->_field = substr($field, 7);
359         //$heading = $field;
360         $this->dbi = &$GLOBALS['request']->getDbh();
361         $this->_PageList_Column_base($this->_field);
362     }
363     
364     function _getValue($page, &$revision_handle) {
365         if (is_object($page)) $text = $page->getName();
366         else $text = $page;
367         $trans = $this->_plugin->translate($text, $this->_field, $this->_from_lang);
368         // how to markup untranslated words and not existing pages?
369         // untranslated: (TODO) link to translation editor
370         if ($trans == $text or // untranslated
371             (($this->_from_lang != 'en') and 
372              ($this->_field != 'en') and
373              ($trans == $this->_plugin->translate($text, 'en', $this->_from_lang))
374              ))
375         {    
376             global $WikiTheme;
377             $link = $WikiTheme->linkUnknownWikiWord($trans);
378             if (!($this->_noT or $this->_nolinks) and $this->dbi->isWikiPage($trans)) {
379                 $url = WikiURL($trans, array('action' => 'TranslateText','lang' => $this->_field));
380                 $button = $WikiTheme->makeButton('T', $url);
381                 $button->addTooltip(sprintf(_("Define the translation for %s in %s"), $trans, $this->_field));
382                 $link = HTML::span($button);
383                 $link->setAttr('class', 'wikiunknown');
384                 $text = HTML::span($WikiTheme->maybeSplitWikiWord($trans));
385                 $text->setAttr('style', 'text-decoration:line-through');
386                 $link->pushContent($text);
387                 return $link;
388             } elseif (is_object($page))
389                 return '';
390             else                        // not existing: empty
391                 return '';
392         } elseif (is_object($page)) {
393             if (!$this->_nolinks)
394                 return WikiLink($trans, 'auto');
395             else
396                 return $trans;
397         } else {
398             return $trans;
399         }
400     }
401 }
402
403 // $Log: not supported by cvs2svn $
404 // Revision 1.13  2004/06/18 14:38:22  rurban
405 // adopt new PageList style
406 //
407 // Revision 1.12  2004/06/17 10:39:18  rurban
408 // fix reverse translation of possible actionpage
409 //
410 // Revision 1.11  2004/06/14 11:31:39  rurban
411 // renamed global $Theme to $WikiTheme (gforge nameclash)
412 // inherit PageList default options from PageList
413 //   default sortby=pagename
414 // use options in PageList_Selectable (limit, sortby, ...)
415 // added action revert, with button at action=diff
416 // added option regex to WikiAdminSearchReplace
417 //
418 // Revision 1.10  2004/05/03 21:57:47  rurban
419 // locale updates: we previously lost some words because of wrong strings in
420 //   PhotoAlbum, german rewording.
421 // fixed $_SESSION registering (lost session vars, esp. prefs)
422 // fixed ending slash in listAvailableLanguages/Themes
423 //
424 // Revision 1.9  2004/05/03 20:44:58  rurban
425 // fixed gettext strings
426 // new SqlResult plugin
427 // _WikiTranslation: fixed init_locale
428 //
429 // Revision 1.8  2004/05/02 21:26:38  rurban
430 // limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
431 //   because they will not survive db sessions, if too large.
432 // extended action=upgrade
433 // some WikiTranslation button work
434 // revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
435 // some temp. session debug statements
436 //
437 // Revision 1.7  2004/05/02 15:10:08  rurban
438 // new finally reliable way to detect if /index.php is called directly
439 //   and if to include lib/main.php
440 // new global AllActionPages
441 // SetupWiki now loads all mandatory pages: HOME_PAGE, action pages, and warns if not.
442 // WikiTranslation what=buttons for Carsten to create the missing MacOSX buttons
443 // PageGroupTestOne => subpages
444 // renamed PhpWikiRss to PhpWikiRecentChanges
445 // more docs, default configs, ...
446 //
447 // Revision 1.6  2004/04/21 04:29:50  rurban
448 // write WikiURL consistently (not WikiUrl)
449 //
450 // Revision 1.5  2004/03/17 15:38:03  rurban
451 // more translations
452 //
453 // Revision 1.4  2004/03/17 13:20:31  rurban
454 // Placeholder for all yet untranslated pgsrc pagenames. Add german translations of these.
455 //
456 // Revision 1.3  2004/03/16 20:22:32  rurban
457 // added link to TranslateText action
458 //
459 // Revision 1.2  2004/03/16 15:47:27  rurban
460 // added match, fixed reverse translation, added page=, what=allpages, what=wikiwords, fixed what=pages, simplified _PageList_Column_custom
461 //
462 // Revision 1.1  2004/03/14 16:45:10  rurban
463 // Just the page matrix for now.
464 // doesn't work yet, if the default langauge != en
465 //
466 //
467
468 // For emacs users
469 // Local Variables:
470 // mode: php
471 // tab-width: 8
472 // c-basic-offset: 4
473 // c-hanging-comment-ender-p: nil
474 // indent-tabs-mode: nil
475 // End:
476 ?>