]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/_WikiTranslation.php
added match, fixed reverse translation, added page=, what=allpages, what=wikiwords...
[SourceForge/phpwiki.git] / lib / plugin / _WikiTranslation.php
1 <?php // -*-php-*-
2 rcs_id('$Id: _WikiTranslation.php,v 1.2 2004-03-16 15:47:27 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 require_once('lib/PageList.php');
46
47 class WikiPlugin__WikiTranslation
48 extends WikiPlugin
49 {
50     function getName() {
51         return _("_WikiTranslation");
52     }
53
54     function getDescription() {
55         return _("Show translations of various words or pages");
56     }
57
58     function getVersion() {
59         return preg_replace("/[Revision: $]/", '',
60                             "\$Revision: 1.2 $");
61     }
62
63     function getDefaultArguments() {
64         return 
65             array( 'languages'  => '',  // comma delimited string of de,en,sv,...
66                    'string'     => '',  
67                    'page'       => '',  // use a translation service
68                    'what'       => 'pages', // or 'buttons', 'plugins' or 'wikiwords'
69
70                    'match'         => '*',
71                    'from_lang'     => false,
72                    'include_empty' => false,
73                    'exclude'       => '',
74                    'sortby'        => '',
75                    'limit'         => 0,
76                    'debug'         => false
77                  );
78     }
79
80     function init_locale($lang) {
81         if ($lang != $this->lang)
82             update_locale($lang);
83         // gettext module loaded: must load the LC_MESSAGES php hash
84         if (function_exists ('bindtextdomain')) {
85             include (FindLocalizedFile("LC_MESSAGES/phpwiki.php", 0,'reinit'));
86         } elseif ($lang == 'en') {
87             //hack alert! we need hash for stepping through it, even if it's in the wrong language
88             include (FindFile("locale/de/LC_MESSAGES/phpwiki.php", 0,'reinit'));
89             foreach ($locale as $en => $de) {
90                 $locale[$en] = $en;
91             }
92         // we already have a $locale, but maybe it's in the wrong language
93         } elseif ($lang != $this->lang or empty($GLOBALS['locale'])) {
94             include (FindFile("LC_MESSAGES/phpwiki.php", 0,'reinit'));
95         } else {
96            $locale = & $GLOBALS['locale'];
97         }
98         $this->_locales[$lang] = $locale;
99     }
100
101     // reverse translation: 
102     function translate_to_en($text,$lang=false) {
103         if (!$lang) $lang = $this->lang; // current locale
104         if ($lang == 'en') return $text;
105
106         $this->_locales = array();
107         $this->_reverse_locales = array();
108
109         if (!isset($this->_locales[$lang])) {
110             $this->init_locale($lang);
111         }
112         assert(!empty($this->_locales[$lang]));
113         if (!isset($this->_reverse_locales[$lang])) {
114             // and now do a reverse lookup in the $locale hash
115             $this->_reverse_locales[$lang] = array_flip($this->_locales[$lang]);
116         }
117         if (!empty($this->_reverse_locales[$lang][$text])) {
118             return $this->_reverse_locales[$lang][$text];
119         } else {
120             return $text;
121         }
122     }
123
124     function translate($text,$to_lang,$from_lang=false) {
125         if (!$from_lang) $from_lang = $this->lang; // current locale
126         if ($from_lang == $to_lang) return $text;
127         // speed up hash lookup. not needed for gettext module
128         if (!isset($this->_locales[$from_lang]) and !function_exists('bindtextdomain')) {
129             $this->init_locale($from_lang);
130         }
131         if ($from_lang != 'en') {
132             // get reverse gettext: translate to english
133             $en = $this->translate_to_en($text,$from_lang);
134             // and then to target
135             update_locale($to_lang);
136             $result = gettext($en);
137             update_locale($from_lang);
138         } else {
139             if ($from_lang != $to_lang) {
140                 update_locale($to_lang);
141             }
142             $result = gettext($text);
143             if ($from_lang != $to_lang) {
144                 update_locale($from_lang);
145             }
146         }
147         return $result;
148     }
149                 
150     function run($dbi, $argstr, $request, $basepage) {
151         extract($this->getArgs($argstr, $request));
152         $this->request = &$request;
153         if (!$from_lang) $from_lang = $request->getPref('lang');
154         if (!$from_lang) $from_lang = $GLOBALS['LANG'];
155         $this->lang = $from_lang;
156
157         if (empty($languages)) {
158             // from lib/plugin/UserPreferences.php
159             $available_languages = array();
160             if ($from_lang != 'en')
161                 array_push($available_languages, 'en');
162             $dir_root = 'locale/';
163             if (defined('PHPWIKI_DIR'))
164                 $dir_root = PHPWIKI_DIR . "/$dir_root";
165             $dir = dir($dir_root);
166             if ($dir) {
167                 while ($entry = $dir->read()) {
168                     if (is_dir($dir_root.$entry)
169                         && (substr($entry,0,1) != '.')
170                         && $entry != 'po'
171                         && $entry != $from_lang
172                         && $entry != 'CVS') {
173                         array_push($available_languages, $entry);
174                     }
175                 }
176                 $dir->close();
177             }
178             if (in_array($from_lang,$available_languages))
179                 $languages = $available_languages;
180             else
181                 $languages = array_merge($available_languages,array($from_lang));
182         } elseif (strstr($languages,',')) {
183             $languages = explode(',',$languages);
184         } else {
185             $languages = array($languages);
186         }
187         $to_lang = $languages[0];
188         if (!empty($string) and count($languages)==1) {
189             return $this->translate($string,$to_lang,$from_lang);
190         }
191         if (!empty($page)) {
192             $pagename = $page;
193             if ($dbi->isWikiPage($pagename)) {
194                 $url = '';
195                 // google can only translate from english and french
196                 if (in_array($from_lang,array('en','fr'))) {
197                     $url = "http://translate.google.com/translate";
198                     $url .= "?langpair=" . urlencode($from_lang."|".$to_lang);
199                     $url .= "&u=" . urlencode(WikiUrl($pagename,false,true));
200                 }
201                 // redirect or transclude?
202                 if ($url)
203                     return $request->redirect($url);
204                 return HTML(fmt("TODO: Google can only translate from english and french. Find a translation service for %s to language %s",
205                                 WikiUrl($pagename,false,true),
206                                 $to_lang));
207             } else
208                 return $this->error(fmt("%s is empty",$pagename));
209         }
210         
211         $pagelist = new PageList('', $exclude, $this->getArgs($argstr, $request));
212         $pagelist->_columns[0]->_heading = "$from_lang";
213         foreach ($languages as $lang) {
214             if ($lang == $from_lang) continue;
215             $field = "custom:$lang";
216             $column = new _PageList_Column_custom($field,$from_lang,$this);
217             $pagelist->_types["custom"] = $column;
218             $pagelist->_addColumn($field);
219         }
220         if (!empty($string)) {
221             $pagelist->addPage( $string );
222             return $pagelist;
223         }
224         switch ($what) {
225         case 'allpages':
226             $pagelist->addPages( $dbi->getAllPages($include_empty, $sortby, $limit) );
227             break;
228         case 'pages':
229             // not all pages, only the pgsrc pages
230             if (!is_array($exclude))
231                 $exclude = $pagelist->explodePageList($exclude,false,$sortby,$limit);
232             $path = FindLocalizedFile(WIKI_PGSRC);
233             $pgsrc = new fileSet($path);
234             foreach ($pgsrc->getFiles($exclude,$sortby,$limit) as $pagename) {
235                 $pagename = urldecode($pagename);
236                 if (substr($pagename,-1,1) == '~') continue;
237                 if (in_array($pagename, $exclude))
238                     continue;             // exclude page.
239                 if ($match != '*' and !glob_match($match,$pagename))
240                     continue;
241                 $page_handle = $dbi->getPage($pagename);
242                 $pagelist->addPage( $page_handle );
243             }
244             break;
245         case 'wikiwords':
246             if (!isset($this->_locales[$from_lang])) {
247                 $this->init_locale($from_lang);
248             }
249             $locale = & $this->_locales[$from_lang];
250             if (is_array($locale)) {
251                 $count = 0;
252                 foreach ($locale as $from => $to) {
253                     if ($match != '*' and !glob_match($match,$from))
254                         continue;
255                     if (isWikiWord($from)) {
256                         $count++;
257                         $pagelist->addPage( $from );
258                         if ($limit and $count > $limit) break;
259                     }
260                 }
261             }
262             break;
263         }
264         return $pagelist;
265     }
266 };
267
268 class _PageList_Column_custom extends _PageList_Column {
269     function _PageList_Column_custom($field, $from_lang, $plugin) {
270         $this->_field = $field;
271         $this->_from_lang = $from_lang;
272         $this->_plugin =& $plugin;
273         $this->_iscustom = substr($field, 0, 7) == 'custom:';
274         if ($this->_iscustom)
275             $this->_field = substr($field, 7);
276         $heading = $field;
277         $this->dbi = &$GLOBALS['request']->getDbh();
278         $this->_PageList_Column_base($field);
279     }
280     
281     function _getValue($page, &$revision_handle) {
282         if (is_object($page)) $text = $page->getName();
283         else $text = $page;
284         $trans = $this->_plugin->translate($text, $this->_field, $this->_from_lang);
285         // how to markup untranslated words and not existing pages?
286         // untranslated: (TODO) link to translation editor
287         if ($trans == $text) {          // untranslated
288             global $Theme;
289             if ($this->dbi->isWikiPage($trans))
290                 return HTML::span(array('class'=>'wikipage',
291                                         'style'=>'text-decoration:line-through'),$trans);
292             elseif (is_object($page))
293                 return '';
294             else                        // not existing: empty
295                 return '';
296         } elseif (is_object($page)) {
297             return WikiLink($trans,'auto');
298         } else {
299             return $trans;
300         }
301     }
302 }
303
304 // $Log: not supported by cvs2svn $
305 // Revision 1.1  2004/03/14 16:45:10  rurban
306 // Just the page matrix for now.
307 // doesn't work yet, if the default langauge != en
308 //
309 //
310
311 // For emacs users
312 // Local Variables:
313 // mode: php
314 // tab-width: 8
315 // c-basic-offset: 4
316 // c-hanging-comment-ender-p: nil
317 // indent-tabs-mode: nil
318 // End:
319 ?>