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