]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/_WikiTranslation.php
new finally reliable way to detect if /index.php is called directly
[SourceForge/phpwiki.git] / lib / plugin / _WikiTranslation.php
1 <?php // -*-php-*-
2 rcs_id('$Id: _WikiTranslation.php,v 1.7 2004-05-02 15:10:08 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 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     _("PageGroupTestFour") .','.
76     _("PageGroupTestOne") .','.
77     _("PageGroupTestThree") .','.
78     _("PageGroupTestTwo") .','.
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.7 $");
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         // gettext module loaded: must load the LC_MESSAGES php hash
148         if (function_exists ('bindtextdomain')) {
149             include (FindLocalizedFile("LC_MESSAGES/phpwiki.php", 0,'reinit'));
150         } elseif ($lang == 'en') {
151             //hack alert! we need hash for stepping through it, even if it's in the wrong language
152             include (FindFile("locale/de/LC_MESSAGES/phpwiki.php", 0,'reinit'));
153             foreach ($locale as $en => $de) {
154                 $locale[$en] = $en;
155             }
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("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         extract($this->getArgs($argstr, $request));
216         $this->request = &$request;
217         if (!$from_lang) $from_lang = $request->getPref('lang');
218         if (!$from_lang) $from_lang = $GLOBALS['LANG'];
219         $this->lang = $from_lang;
220         $this->noT = $noT;
221         $this->nolinks = $nolinks;
222
223         if (empty($languages)) {
224             // from lib/plugin/UserPreferences.php
225             $available_languages = array();
226             if ($from_lang != 'en')
227                 array_push($available_languages, 'en');
228             $dir_root = 'locale/';
229             if (defined('PHPWIKI_DIR'))
230                 $dir_root = PHPWIKI_DIR . "/$dir_root";
231             $dir = dir($dir_root);
232             if ($dir) {
233                 while ($entry = $dir->read()) {
234                     if (is_dir($dir_root.$entry)
235                         && (substr($entry,0,1) != '.')
236                         && $entry != 'po'
237                         && $entry != $from_lang
238                         && $entry != 'CVS') {
239                         array_push($available_languages, $entry);
240                     }
241                 }
242                 $dir->close();
243             }
244             if (in_array($from_lang,$available_languages))
245                 $languages = $available_languages;
246             else
247                 $languages = array_merge($available_languages,array($from_lang));
248         } elseif (strstr($languages,',')) {
249             $languages = explode(',',$languages);
250         } else {
251             $languages = array($languages);
252         }
253         if (in_array('zh',$languages) or in_array('ja',$languages)) {
254             // if the current charset != utf-8 the text will not be displayed correctly
255             // but here we cannot change the header anymore. so we can decide to ignore them, 
256             // or display them with all the errors.
257             $GLOBALS['charset'] = 'utf-8';
258         }
259         $to_lang = $languages[0];
260         if (!empty($string) and count($languages)==1) {
261             return $this->translate($string,$to_lang,$from_lang);
262         }
263         if (!empty($page)) {
264             $pagename = $page;
265             if ($dbi->isWikiPage($pagename)) {
266                 $url = '';
267                 // google can only translate from english and french
268                 if (in_array($from_lang,array('en','fr'))) {
269                     $url = "http://translate.google.com/translate";
270                     $url .= "?langpair=" . urlencode($from_lang."|".$to_lang);
271                     $url .= "&u=" . urlencode(WikiURL($pagename,false,true));
272                 }
273                 // redirect or transclude?
274                 if ($url)
275                     return $request->redirect($url);
276                 return HTML(fmt("TODO: Google can only translate from english and french. Find a translation service for %s to language %s",
277                                 WikiURL($pagename,false,true),
278                                 $to_lang));
279             } else
280                 return $this->error(fmt("%s is empty",$pagename));
281         }
282         
283         $pagelist = new PageList('', $exclude, $this->getArgs($argstr, $request));
284         $pagelist->_columns[0]->_heading = "$from_lang";
285         foreach ($languages as $lang) {
286             if ($lang == $from_lang) continue;
287             $field = "custom:$lang";
288             $column = new _PageList_Column_custom($field,$from_lang,$this);
289             $pagelist->_types["custom"] = $column;
290             $pagelist->_addColumn($field);
291         }
292         if (!empty($string)) {
293             $pagelist->addPage( $string );
294             return $pagelist;
295         }
296         switch ($what) {
297         case 'allpages':
298             $pagelist->addPages( $dbi->getAllPages($include_empty, $sortby, $limit) );
299             break;
300         case 'pages':
301             // not all pages, only the pgsrc pages
302             if (!is_array($exclude))
303                 $exclude = $pagelist->explodePageList($exclude,false,$sortby,$limit);
304             $path = FindLocalizedFile(WIKI_PGSRC);
305             $pgsrc = new fileSet($path);
306             foreach ($pgsrc->getFiles($exclude,$sortby,$limit) as $pagename) {
307                 $pagename = urldecode($pagename);
308                 if (substr($pagename,-1,1) == '~') continue;
309                 if (in_array($pagename, $exclude))
310                     continue;             // exclude page.
311                 if ($match != '*' and !glob_match($match,$pagename))
312                     continue;
313                 $page_handle = $dbi->getPage($pagename);
314                 $pagelist->addPage( $page_handle );
315             }
316             break;
317         case 'wikiwords':
318             if (!isset($this->_locales[$from_lang])) {
319                 $this->init_locale($from_lang);
320             }
321             $locale = & $this->_locales[$from_lang];
322             if (is_array($locale)) {
323                 $count = 0;
324                 foreach ($locale as $from => $to) {
325                     if ($match != '*' and !glob_match($match,$from))
326                         continue;
327                     if (isWikiWord($from)) {
328                         $count++;
329                         $pagelist->addPage( $from );
330                         if ($limit and $count > $limit) break;
331                     }
332                 }
333             }
334             break;
335         // all Button texts, which need a localized .png
336         // where to get them from? templates/*.tmpl: Button() and WikiLink(?,'button')
337         // navbar links, actionpages, and admin requests
338         case 'buttons':
339             $buttons = $GLOBALS['AllActionPages'];
340             $fileset = new FileSet(FindFile("themes/MacOSX/buttons/en"), "*.png");
341             foreach ($fileset->getFiles() as $file) {
342                 $b = urldecode(substr($file,0,-4));
343                 if (!in_array($b,$buttons))
344                     $buttons[] = $b;
345             }
346             $count = 0;
347             foreach ($buttons as $button) {
348                 $pagelist->addPage( $button );
349                 if ($limit and ++$count > $limit) break;
350             }
351             break;
352         }
353         return $pagelist;
354     }
355 };
356
357 class _PageList_Column_custom extends _PageList_Column {
358     function _PageList_Column_custom($field, $from_lang, $plugin) {
359         $this->_field = $field;
360         $this->_from_lang = $from_lang;
361         $this->_plugin =& $plugin;
362         $this->_noT = $plugin->noT;
363         $this->_nolinks = $plugin->nolinks;
364         $this->_iscustom = substr($field, 0, 7) == 'custom:';
365         if ($this->_iscustom)
366             $this->_field = substr($field, 7);
367         $heading = $field;
368         $this->dbi = &$GLOBALS['request']->getDbh();
369         $this->_PageList_Column_base($field);
370     }
371     
372     function _getValue($page, &$revision_handle) {
373         if (is_object($page)) $text = $page->getName();
374         else $text = $page;
375         $trans = $this->_plugin->translate($text, $this->_field, $this->_from_lang);
376         // how to markup untranslated words and not existing pages?
377         // untranslated: (TODO) link to translation editor
378         if ($trans == $text or // untranslated
379             (($this->_from_lang != 'en') and 
380              ($this->_field != 'en') and
381              ($trans == $this->_plugin->translate($text, 'en', $this->_from_lang))
382              ))
383         {    
384             global $Theme;
385             $link = $Theme->linkUnknownWikiWord($trans);
386             if (!($this->_noT or $this->_nolinks) and $this->dbi->isWikiPage($trans)) {
387                 $url = WikiURL($trans, array('action' => 'TranslateText','lang' => $this->_field));
388                 $button = $Theme->makeButton('T', $url);
389                 $button->addTooltip(sprintf(_("Define the translation for %s in %s"), $trans, $this->_field));
390                 $link = HTML::span($button);
391                 $link->setAttr('class', 'wikiunknown');
392                 $text = HTML::span($Theme->maybeSplitWikiWord($trans));
393                 $text->setAttr('style', 'text-decoration:line-through');
394                 $link->pushContent($text);
395                 return $link;
396             } elseif (is_object($page))
397                 return '';
398             else                        // not existing: empty
399                 return '';
400         } elseif (is_object($page)) {
401             if (!$this->_nolinks)
402                 return WikiLink($trans,'auto');
403             else
404                 return $trans;
405         } else {
406             return $trans;
407         }
408     }
409 }
410
411 // $Log: not supported by cvs2svn $
412 // Revision 1.6  2004/04/21 04:29:50  rurban
413 // write WikiURL consistently (not WikiUrl)
414 //
415 // Revision 1.5  2004/03/17 15:38:03  rurban
416 // more translations
417 //
418 // Revision 1.4  2004/03/17 13:20:31  rurban
419 // Placeholder for all yet untranslated pgsrc pagenames. Add german translations of these.
420 //
421 // Revision 1.3  2004/03/16 20:22:32  rurban
422 // added link to TranslateText action
423 //
424 // Revision 1.2  2004/03/16 15:47:27  rurban
425 // added match, fixed reverse translation, added page=, what=allpages, what=wikiwords, fixed what=pages, simplified _PageList_Column_custom
426 //
427 // Revision 1.1  2004/03/14 16:45:10  rurban
428 // Just the page matrix for now.
429 // doesn't work yet, if the default langauge != en
430 //
431 //
432
433 // For emacs users
434 // Local Variables:
435 // mode: php
436 // tab-width: 8
437 // c-basic-offset: 4
438 // c-hanging-comment-ender-p: nil
439 // indent-tabs-mode: nil
440 // End:
441 ?>