2 rcs_id('$Id: _WikiTranslation.php,v 1.7 2004-05-02 15:10:08 rurban Exp $');
4 Copyright 2004 $ThePhpWikiProgrammingTeam
6 This file is part of PhpWiki.
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.
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.
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
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
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.
42 * @author: Reini Urban
45 /* Container for untranslated pagenames. Needed to show up in locale/po/phpwiki.pot */
47 _("AddCommentPlugin") .','.
48 _("AddingPages") .','.
49 _("AuthorHistoryPlugin") .','.
51 _("CalendarListPlugin") .','.
52 _("CalendarPlugin") .','.
53 _("CategoryCategory") .','.
54 _("CategoryHomePages") .','.
55 _("CommentPlugin") .','.
56 _("CreateTocPlugin") .','.
58 _("EditMetaDataPlugin") .','.
59 _("ExternalSearchPlugin") .','.
61 _("FrameIncludePlugin") .','.
62 _("FullRecentChanges") .','.
63 _("HelloWorldPlugin") .','.
64 _("HomePageAlias") .','.
65 _("IncludePagePlugin") .','.
68 _("MagicPhpWikiURLs") .','.
69 _("MoreAboutMechanics") .','.
70 _("NewMarkupTestPage") .','.
71 _("OldMarkupTestPage") .','.
72 _("OldStyleTablePlugin") .','.
74 _("PageGroupTest") .','.
75 _("PageGroupTestFour") .','.
76 _("PageGroupTestOne") .','.
77 _("PageGroupTestThree") .','.
78 _("PageGroupTestTwo") .','.
79 _("PgsrcTranslation") .','.
80 _("PhotoAlbumPlugin") .','.
81 _("PhpHighlightPlugin") .','.
82 _("PhpWeatherPlugin") .','.
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") .','.
102 _("WikiBlogPlugin") .','.
103 _("WikiPlugin") .','.
106 require_once('lib/PageList.php');
108 class WikiPlugin__WikiTranslation
113 return _("_WikiTranslation");
116 function getDescription() {
117 return _("Show translations of various words or pages");
120 function getVersion() {
121 return preg_replace("/[Revision: $]/", '',
122 "\$Revision: 1.7 $");
125 function getDefaultArguments() {
127 array( 'languages' => '', // comma delimited string of de,en,sv,...
129 'page' => '', // use a translation service
130 'what' => 'pages', // or 'buttons', 'plugins' or 'wikiwords'
133 'from_lang' => false,
134 'include_empty' => false,
138 'nolinks' => false, // don't display any links (for development only)
139 'noT' => false, // don't display the T link (for development only)
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) {
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'));
160 $locale = & $GLOBALS['locale'];
162 $this->_locales[$lang] = $locale;
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;
170 $this->_locales = array();
171 $this->_reverse_locales = array();
173 if (!isset($this->_locales[$lang])) {
174 $this->init_locale($lang);
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]);
181 if (!empty($this->_reverse_locales[$lang][$text])) {
182 return $this->_reverse_locales[$lang][$text];
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);
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);
203 if ($from_lang != $to_lang) {
204 update_locale($to_lang);
206 $result = gettext($text);
207 if ($from_lang != $to_lang) {
208 update_locale($from_lang);
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;
221 $this->nolinks = $nolinks;
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);
233 while ($entry = $dir->read()) {
234 if (is_dir($dir_root.$entry)
235 && (substr($entry,0,1) != '.')
237 && $entry != $from_lang
238 && $entry != 'CVS') {
239 array_push($available_languages, $entry);
244 if (in_array($from_lang,$available_languages))
245 $languages = $available_languages;
247 $languages = array_merge($available_languages,array($from_lang));
248 } elseif (strstr($languages,',')) {
249 $languages = explode(',',$languages);
251 $languages = array($languages);
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';
259 $to_lang = $languages[0];
260 if (!empty($string) and count($languages)==1) {
261 return $this->translate($string,$to_lang,$from_lang);
265 if ($dbi->isWikiPage($pagename)) {
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));
273 // redirect or transclude?
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),
280 return $this->error(fmt("%s is empty",$pagename));
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);
292 if (!empty($string)) {
293 $pagelist->addPage( $string );
298 $pagelist->addPages( $dbi->getAllPages($include_empty, $sortby, $limit) );
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))
313 $page_handle = $dbi->getPage($pagename);
314 $pagelist->addPage( $page_handle );
318 if (!isset($this->_locales[$from_lang])) {
319 $this->init_locale($from_lang);
321 $locale = & $this->_locales[$from_lang];
322 if (is_array($locale)) {
324 foreach ($locale as $from => $to) {
325 if ($match != '*' and !glob_match($match,$from))
327 if (isWikiWord($from)) {
329 $pagelist->addPage( $from );
330 if ($limit and $count > $limit) 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
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))
347 foreach ($buttons as $button) {
348 $pagelist->addPage( $button );
349 if ($limit and ++$count > $limit) break;
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);
368 $this->dbi = &$GLOBALS['request']->getDbh();
369 $this->_PageList_Column_base($field);
372 function _getValue($page, &$revision_handle) {
373 if (is_object($page)) $text = $page->getName();
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))
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);
396 } elseif (is_object($page))
398 else // not existing: empty
400 } elseif (is_object($page)) {
401 if (!$this->_nolinks)
402 return WikiLink($trans,'auto');
411 // $Log: not supported by cvs2svn $
412 // Revision 1.6 2004/04/21 04:29:50 rurban
413 // write WikiURL consistently (not WikiUrl)
415 // Revision 1.5 2004/03/17 15:38:03 rurban
418 // Revision 1.4 2004/03/17 13:20:31 rurban
419 // Placeholder for all yet untranslated pgsrc pagenames. Add german translations of these.
421 // Revision 1.3 2004/03/16 20:22:32 rurban
422 // added link to TranslateText action
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
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
438 // c-hanging-comment-ender-p: nil
439 // indent-tabs-mode: nil