Index: trunk/extensions/Translate/tag/TranslatablePage.php |
— | — | @@ -235,7 +235,7 @@ |
236 | 236 | } |
237 | 237 | |
238 | 238 | |
239 | | - public function getTranslationUrl( $code ) { |
| 239 | + public function getTranslationUrl( $code = false ) { |
240 | 240 | $translate = SpecialPage::getTitleFor( 'Translate' ); |
241 | 241 | $params = array( |
242 | 242 | 'group' => 'page|' . $this->getTitle()->getPrefixedText(), |
— | — | @@ -293,7 +293,11 @@ |
294 | 294 | if ( $t->getSubpageText() === $t->getText() ) continue; |
295 | 295 | $collection = $group->initCollection( $t->getSubpageText() ); |
296 | 296 | $group->fillCollection( $collection ); |
297 | | - $temp[$collection->code] = $this->getPercentageInternal( $collection, $markedRevs ); |
| 297 | + |
| 298 | + $percent = $this->getPercentageInternal( $collection, $markedRevs ); |
| 299 | + // To avoid storing 40 decimals of inaccuracy, truncate to two decimals |
| 300 | + $temp[$collection->code] = sprintf( '%.2f', $percent ); |
| 301 | + |
298 | 302 | } |
299 | 303 | // English is always up-to-date |
300 | 304 | $temp['en'] = 1.00; |
— | — | @@ -314,7 +318,7 @@ |
315 | 319 | |
316 | 320 | $score = 1; |
317 | 321 | |
318 | | - // Fuzzy halves |
| 322 | + // Fuzzy halves score |
319 | 323 | if ( $message->fuzzy() ) $score *= 0.5; |
320 | 324 | |
321 | 325 | // Reduce 20% for every newer revision than what is translated against |
— | — | @@ -334,6 +338,8 @@ |
335 | 339 | } |
336 | 340 | $total += $score; |
337 | 341 | } |
| 342 | + |
| 343 | + // Divide score by count to get completion percentage |
338 | 344 | return $total/$count; |
339 | 345 | } |
340 | 346 | |
— | — | @@ -365,6 +371,20 @@ |
366 | 372 | } |
367 | 373 | return $tagcache[$tag]; |
368 | 374 | } |
| 375 | + |
| 376 | + public static function isTranslationPage( Title $title ) { |
| 377 | + if ( $title->getText() === $title->getBaseText() ) return false; |
| 378 | + |
| 379 | + $page = TranslatablePage::newFromTitle( |
| 380 | + self::changeTitleText( $title, $title->getBaseText() ) ); |
| 381 | + |
| 382 | + if ( $page->getMarkedTag() === null ) return false; |
| 383 | + return $page; |
| 384 | + } |
| 385 | + |
| 386 | + public static function changeTitleText( Title $title, $text ) { |
| 387 | + return Title::makeTitleSafe( $title->getNamespace(), $text ); |
| 388 | + } |
369 | 389 | } |
370 | 390 | |
371 | 391 | class TPException extends MWException { |
Index: trunk/extensions/Translate/tag/PageTranslationHooks.php |
— | — | @@ -28,14 +28,13 @@ |
29 | 29 | |
30 | 30 | public static function onSectionSave( $article, $user, $text, $summary, $minor, |
31 | 31 | $_, $_, $flags, $revision ) { |
32 | | - global $wgTranslateFuzzyBotName; |
33 | 32 | $title = $article->getTitle(); |
34 | 33 | |
35 | 34 | // Some checks |
36 | 35 | |
37 | 36 | // We are only interested in the translations namespace |
38 | 37 | if ( $title->getNamespace() != NS_TRANSLATIONS ) return true; |
39 | | - // Do not trigger renders for fuzzybot or fuzzy |
| 38 | + // Do not trigger renders for fuzzy |
40 | 39 | if ( strpos( $text, TRANSLATE_FUZZY ) !== false ) return true; |
41 | 40 | |
42 | 41 | // Figure out the group |
— | — | @@ -149,23 +148,25 @@ |
150 | 149 | $status = $page->getTranslationPercentages(); |
151 | 150 | if ( !$status ) return ''; |
152 | 151 | |
153 | | - global $wgLang; |
154 | | - |
155 | | - // Sort by language code |
| 152 | + // Sort by language code, which seems to be the only sane method |
156 | 153 | ksort( $status ); |
157 | 154 | |
158 | | - // $lobj = $parser->getFunctionLang(); |
159 | 155 | $sk = $parser->mOptions->getSkin(); |
160 | | - $legend = wfMsg( 'otherlanguages' ); |
161 | 156 | |
162 | | - global $wgTranslateCssLocation; |
| 157 | + /* We rely on $wgLang, which should not matter as |
| 158 | + * languages are cached per language. However it |
| 159 | + * would be nicer to use $parser->getFunctionLang(); |
| 160 | + * but that needs to be set correct first. */ |
| 161 | + // $lobj = $parser->getFunctionLang(); |
| 162 | + global $wgTranslateCssLocation, $wgLang; |
163 | 163 | |
164 | 164 | $languages = array(); |
165 | 165 | foreach ( $status as $code => $percent ) { |
166 | 166 | $name = TranslateUtils::getLanguageName( $code, false, $wgLang->getCode() ); |
167 | 167 | |
| 168 | + /* Percentages are too accurate and take more |
| 169 | + * space than plain images */ |
168 | 170 | $percent *= 100; |
169 | | - if ( $percent < 10 ) continue; // Hide.. not very useful |
170 | 171 | if ( $percent < 20 ) $image = 1; |
171 | 172 | elseif ( $percent < 40 ) $image = 2; |
172 | 173 | elseif ( $percent < 60 ) $image = 3; |
— | — | @@ -173,15 +174,26 @@ |
174 | 175 | else $image = 5; |
175 | 176 | |
176 | 177 | $percent = Xml::element( 'img', array( |
177 | | - 'src' => "$wgTranslateCssLocation/images/prog-$image.png" |
| 178 | + 'src' => "$wgTranslateCssLocation/images/prog-$image.png", |
| 179 | + 'alt' => "$percent%", |
| 180 | + 'title' => "$percent%", |
178 | 181 | ) ); |
179 | 182 | $label = "$name $percent"; |
180 | 183 | |
| 184 | + // Add links to other languages |
181 | 185 | $suffix = ( $code === 'en' ) ? '' : "/$code"; |
182 | 186 | $_title = Title::makeTitle( $title->getNamespace(), $title->getDBKey() . $suffix ); |
183 | | - $languages[] = $sk->link( $_title, $label ); |
| 187 | + |
| 188 | + // For some reason self-links are not done automatically |
| 189 | + if ( $parser->getTitle()->getText() === $_title->getText() ) { |
| 190 | + $languages[] = "<b>$label</b>"; |
| 191 | + } else { |
| 192 | + $languages[] = $sk->link( $_title, $label ); |
| 193 | + } |
184 | 194 | } |
185 | 195 | |
| 196 | + wfLoadExtensionMessages( 'PageTranslation' ); |
| 197 | + $legend = wfMsg( 'tpt-languages-legend' ); |
186 | 198 | $languages = implode( ' • ', $languages ); |
187 | 199 | |
188 | 200 | return <<<FOO |
— | — | @@ -189,7 +201,7 @@ |
190 | 202 | <table><tbody> |
191 | 203 | |
192 | 204 | <tr valign="top"> |
193 | | -<td class="mw-pt-languages-label"><b>$legend:</b></td> |
| 205 | +<td class="mw-pt-languages-label"><b>$legend</b></td> |
194 | 206 | <td class="mw-pt-languages-list">$languages</td></tr> |
195 | 207 | |
196 | 208 | </tbody></table> |
— | — | @@ -197,6 +209,7 @@ |
198 | 210 | FOO; |
199 | 211 | } |
200 | 212 | |
| 213 | + // When attempting to save |
201 | 214 | public static function tpSyntaxCheck( $article, $user, $text, $summary, |
202 | 215 | $minor, $_, $_, $flags, $status ) { |
203 | 216 | // Quick escape on normal pages |
— | — | @@ -204,6 +217,8 @@ |
205 | 218 | |
206 | 219 | $page = TranslatablePage::newFromText( $article->getTitle(), $text ); |
207 | 220 | try { |
| 221 | + /* This does not catch all problems yet, |
| 222 | + * like markup spanning between sections. */ |
208 | 223 | $page->getParse(); |
209 | 224 | } catch ( TPException $e ) { |
210 | 225 | call_user_func_array( array( $status, 'fatal' ), $ret ); |
— | — | @@ -246,18 +261,24 @@ |
247 | 262 | } elseif( $title->getBaseText() != $title->getText() ) { |
248 | 263 | $newtitle = Title::makeTitle( $title->getNamespace(), $title->getBaseText() ); |
249 | 264 | |
250 | | - if ( $newtitle && $newtitle->exists() ) { |
251 | | - $page = TranslatablePage::newFromTitle( $newtitle ); |
| 265 | + // Base page does not exists, cannot be translatable page |
| 266 | + if ( !$newtitle || !$newtitle->exists() ) return true; |
252 | 267 | |
253 | | - if ( $page->getMarkedTag() && !self::$allowTargetEdit) { |
254 | | - wfLoadExtensionMessages( 'PageTranslation' ); |
255 | | - $result = array( |
256 | | - 'tpt-target-page', |
257 | | - $newtitle->getPrefixedText(), |
258 | | - $page->getTranslationUrl( $title->getSubpageText() ) |
259 | | - ); |
260 | | - return false; |
261 | | - } |
| 268 | + // Local override of fuzzybot is allowed |
| 269 | + global $wgTranslateFuzzyBotName; |
| 270 | + if ( self::$allowTargetEdit || |
| 271 | + $user->getName() === $wgTranslateFuzzyBotName ) return true; |
| 272 | + |
| 273 | + // Proceed to check whether we need to block |
| 274 | + $page = TranslatablePage::newFromTitle( $newtitle ); |
| 275 | + if ( $page->getMarkedTag() ) { |
| 276 | + wfLoadExtensionMessages( 'PageTranslation' ); |
| 277 | + $result = array( |
| 278 | + 'tpt-target-page', |
| 279 | + $newtitle->getPrefixedText(), |
| 280 | + $page->getTranslationUrl( $title->getSubpageText() ) |
| 281 | + ); |
| 282 | + return false; |
262 | 283 | } |
263 | 284 | } |
264 | 285 | |
— | — | @@ -276,6 +297,7 @@ |
277 | 298 | |
278 | 299 | $dbw = wfGetDB( DB_MASTER ); |
279 | 300 | foreach ( $tags as $tag ) { |
| 301 | + // TODO: use insert ignore |
280 | 302 | $field = array( 'rtt_name' => $tag ); |
281 | 303 | $ret = $dbw->selectField( 'revtag_type', 'rtt_name', $field, __METHOD__ ); |
282 | 304 | if ( $ret !== $tag ) $dbw->insert( 'revtag_type', $field, __METHOD__ ); |
— | — | @@ -283,38 +305,48 @@ |
284 | 306 | return true; |
285 | 307 | } |
286 | 308 | |
| 309 | + // TODO: fix the name |
287 | 310 | public static function test(&$article, &$outputDone, &$pcache) { |
288 | 311 | global $wgOut; |
289 | 312 | if ( !$article->getOldID() ) { |
290 | | - $wgOut->addHTML( self::getHeader( $article->getTitle() ) ); |
291 | | - } else { |
292 | | - echo "foo"; |
| 313 | + self::header( $article->getTitle() ); |
293 | 314 | } |
294 | 315 | return true; |
295 | 316 | } |
296 | 317 | |
297 | | - public static function getHeader( Title $title, $code = false ) { |
| 318 | + public static function header( Title $title ) { |
298 | 319 | global $wgLang, $wgUser; |
299 | 320 | |
300 | | - $sk = $wgUser->getSkin(); |
301 | 321 | |
302 | 322 | $page = TranslatablePage::newFromTitle( $title ); |
303 | | - |
304 | 323 | $marked = $page->getMarkedTag(); |
305 | 324 | $ready = $page->getReadyTag(); |
306 | 325 | |
307 | | - if ( $marked === false && $ready === false ) return ''; |
| 326 | + if ( $marked || $ready ) { |
| 327 | + self::sourcePageHeader( $page, $marked, $ready ); |
| 328 | + } else { |
| 329 | + self::translationPageHeader( $title ); |
| 330 | + } |
| 331 | + } |
308 | 332 | |
| 333 | + protected static function sourcePageHeader( TranslatablePage $page, |
| 334 | + $marked, $ready ) { |
| 335 | + |
| 336 | + global $wgUser, $wgLang; |
| 337 | + wfLoadExtensionMessages( 'PageTranslation' ); |
| 338 | + |
| 339 | + $title = $page->getTitle(); |
| 340 | + $sk = $wgUser->getSkin(); |
| 341 | + |
309 | 342 | $latest = $title->getLatestRevId(); |
310 | 343 | $canmark = $ready === $latest && $marked !== $latest; |
311 | | - wfLoadExtensionMessages( 'PageTranslation' ); |
312 | 344 | |
313 | 345 | $actions = array(); |
314 | 346 | |
315 | 347 | if ( $marked && $wgUser->isAllowed('translate') ) { |
316 | 348 | $par = array( |
317 | 349 | 'group' => 'page|' . $title->getPrefixedText(), |
318 | | - 'language' => $code ? $code : $wgLang->getCode(), |
| 350 | + 'language' => $wgLang->getCode(), |
319 | 351 | 'task' => 'view' |
320 | 352 | ); |
321 | 353 | $translate = SpecialPage::getTitleFor( 'Translate' ); |
— | — | @@ -331,21 +363,34 @@ |
332 | 364 | $actions[] = $sk->link( $translate, $linkDesc, array(), $par); |
333 | 365 | } |
334 | 366 | |
335 | | - |
336 | | - if ( $code ) { |
337 | | - $legendText = wfMsgHtml( 'translate-tag-legend' ); |
338 | | - $legendOther = wfMsgHtml( 'translate-tag-legend-fallback' ); |
339 | | - $legendFuzzy = wfMsgHtml( 'translate-tag-legend-fuzzy' ); |
340 | | - |
341 | | - $actions[] = "$legendText <span class=\"mw-translate-other\">$legendOther</span>" . |
342 | | - " <span class=\"mw-translate-fuzzy\">$legendFuzzy</span>"; |
343 | | - } |
344 | | - |
345 | | - if ( !count($actions) ) return ''; |
| 367 | + if ( !count($actions) ) return; |
346 | 368 | $legend = "<div style=\"font-size: x-small; text-align: center\">"; |
347 | 369 | $legend .= $wgLang->semicolonList( $actions ); |
348 | 370 | $legend .= '</div><hr />'; |
349 | | - return $legend; |
| 371 | + |
| 372 | + global $wgOut; |
| 373 | + $wgOut->addHTML( $legend ); |
| 374 | + |
350 | 375 | } |
351 | 376 | |
| 377 | + protected static function translationPageHeader( Title $title ) { |
| 378 | + global $wgOut; |
| 379 | + |
| 380 | + // Check if applicable |
| 381 | + $page = TranslatablePage::isTranslationPage( $title ); |
| 382 | + if ( $page === false ) return; |
| 383 | + |
| 384 | + // Get the translation percentage |
| 385 | + $pers = $page->getTranslationPercentages(); |
| 386 | + $per = $pers[$title->getSubpageText()] * 100; |
| 387 | + $titleText = $page->getTitle()->getText(); |
| 388 | + $url = $page->getTranslationUrl( $title->getSubpageText() ); |
| 389 | + |
| 390 | + // Output |
| 391 | + wfLoadExtensionMessages( 'PageTranslation' ); |
| 392 | + $wrap = '<div style="font-size: x-small; text-align: center">$1</div><hr />'; |
| 393 | + $wgOut->wrapWikiMsg( $wrap, array( 'tpt-translation-intro', $url, $titleText, $per) ); |
| 394 | + |
| 395 | + } |
| 396 | + |
352 | 397 | } |
\ No newline at end of file |
Index: trunk/extensions/Translate/PageTranslation.i18n.php |
— | — | @@ -50,10 +50,11 @@ |
51 | 51 | # Source and translation page headers |
52 | 52 | 'translate-tag-translate-link-desc' => 'Translate this page', |
53 | 53 | 'translate-tag-markthis' => 'Mark this page for translation', |
54 | | - 'translate-tag-legend' => 'Legend:', |
55 | | - 'translate-tag-legend-fallback' => 'Translation in other language', |
56 | | - 'translate-tag-legend-fuzzy' => 'Outdated translation', |
| 54 | + 'tpt-translation-intro' => 'This page is a <span class="plainlinks">[$1 translated version]</span> of a page [[$2]] and the translation is $3% complete and up to date. |
| 55 | +<span class="mw-translate-fuzzy">Out-dated translation are marked like this.</span>', |
57 | 56 | |
| 57 | + 'tpt-languages-legend' => 'Other languages:', |
| 58 | + |
58 | 59 | 'tpt-target-page' => 'This page cannot be updated manually. |
59 | 60 | This page is a translation of page [[$1]] and the translation can be updated using [$2 the translation tool].', |
60 | 61 | 'tpt-unknown-page' => 'This namespace is reserved for content page translations. |