2 rcs_id('$Id: _WikiTranslation.php,v 1.2 2004-03-16 15:47:27 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 require_once('lib/PageList.php');
47 class WikiPlugin__WikiTranslation
51 return _("_WikiTranslation");
54 function getDescription() {
55 return _("Show translations of various words or pages");
58 function getVersion() {
59 return preg_replace("/[Revision: $]/", '',
63 function getDefaultArguments() {
65 array( 'languages' => '', // comma delimited string of de,en,sv,...
67 'page' => '', // use a translation service
68 'what' => 'pages', // or 'buttons', 'plugins' or 'wikiwords'
72 'include_empty' => false,
80 function init_locale($lang) {
81 if ($lang != $this->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) {
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'));
96 $locale = & $GLOBALS['locale'];
98 $this->_locales[$lang] = $locale;
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;
106 $this->_locales = array();
107 $this->_reverse_locales = array();
109 if (!isset($this->_locales[$lang])) {
110 $this->init_locale($lang);
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]);
117 if (!empty($this->_reverse_locales[$lang][$text])) {
118 return $this->_reverse_locales[$lang][$text];
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);
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);
139 if ($from_lang != $to_lang) {
140 update_locale($to_lang);
142 $result = gettext($text);
143 if ($from_lang != $to_lang) {
144 update_locale($from_lang);
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;
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);
167 while ($entry = $dir->read()) {
168 if (is_dir($dir_root.$entry)
169 && (substr($entry,0,1) != '.')
171 && $entry != $from_lang
172 && $entry != 'CVS') {
173 array_push($available_languages, $entry);
178 if (in_array($from_lang,$available_languages))
179 $languages = $available_languages;
181 $languages = array_merge($available_languages,array($from_lang));
182 } elseif (strstr($languages,',')) {
183 $languages = explode(',',$languages);
185 $languages = array($languages);
187 $to_lang = $languages[0];
188 if (!empty($string) and count($languages)==1) {
189 return $this->translate($string,$to_lang,$from_lang);
193 if ($dbi->isWikiPage($pagename)) {
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));
201 // redirect or transclude?
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),
208 return $this->error(fmt("%s is empty",$pagename));
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);
220 if (!empty($string)) {
221 $pagelist->addPage( $string );
226 $pagelist->addPages( $dbi->getAllPages($include_empty, $sortby, $limit) );
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))
241 $page_handle = $dbi->getPage($pagename);
242 $pagelist->addPage( $page_handle );
246 if (!isset($this->_locales[$from_lang])) {
247 $this->init_locale($from_lang);
249 $locale = & $this->_locales[$from_lang];
250 if (is_array($locale)) {
252 foreach ($locale as $from => $to) {
253 if ($match != '*' and !glob_match($match,$from))
255 if (isWikiWord($from)) {
257 $pagelist->addPage( $from );
258 if ($limit and $count > $limit) break;
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);
277 $this->dbi = &$GLOBALS['request']->getDbh();
278 $this->_PageList_Column_base($field);
281 function _getValue($page, &$revision_handle) {
282 if (is_object($page)) $text = $page->getName();
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
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))
294 else // not existing: empty
296 } elseif (is_object($page)) {
297 return WikiLink($trans,'auto');
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
316 // c-hanging-comment-ender-p: nil
317 // indent-tabs-mode: nil