Index: trunk/extensions/Translate/MessageGroups.php |
— | — | @@ -974,6 +974,17 @@ |
975 | 975 | return null; |
976 | 976 | } |
977 | 977 | |
| 978 | + /** |
| 979 | + * Subpage language of any in the title is not used. |
| 980 | + */ |
| 981 | + public function getMessageContent( MessageHandle $handle, $code ) { |
| 982 | + $groupId = MessageIndex::getPrimaryGroupId( $handle ); |
| 983 | + $group = MessageGroups::getGroup( $groupId ); |
| 984 | + if ( $group ) { |
| 985 | + return $group->getMessage( $handle->getKey(), $code ); |
| 986 | + } |
| 987 | + } |
| 988 | + |
978 | 989 | } |
979 | 990 | |
980 | 991 | /** |
Index: trunk/extensions/Translate/TranslateEditAddons.php |
— | — | @@ -269,7 +269,8 @@ |
270 | 270 | private static function editBoxes( EditPage $object ) { |
271 | 271 | global $wgOut, $wgRequest; |
272 | 272 | |
273 | | - $th = new TranslationHelpers( $object->mTitle ); |
| 273 | + $groupId = $wgRequest->getText( 'loadgroup', '' ); |
| 274 | + $th = new TranslationHelpers( $object->mTitle, $groupId ); |
274 | 275 | if ( $object->firsttime && !$wgRequest->getCheck( 'oldid' ) && !$wgRequest->getCheck( 'undo' ) ) { |
275 | 276 | $object->textbox1 = (string) $th->getTranslation(); |
276 | 277 | } else { |
Index: trunk/extensions/Translate/utils/MessageIndex.php |
— | — | @@ -20,9 +20,6 @@ |
21 | 21 | /// @var MessageIndex |
22 | 22 | protected static $instance; |
23 | 23 | |
24 | | - /// @var array |
25 | | - protected $index; |
26 | | - |
27 | 24 | /** |
28 | 25 | * @return MessageIndex |
29 | 26 | */ |
— | — | @@ -36,6 +33,33 @@ |
37 | 34 | return self::$instance; |
38 | 35 | } |
39 | 36 | |
| 37 | + |
| 38 | + /** |
| 39 | + * @since 2012-01-14 |
| 40 | + * @return array |
| 41 | + */ |
| 42 | + public static function getGroupIds( MessageHandle $handle ) { |
| 43 | + $namespace = $handle->getTitle()->getNamespace(); |
| 44 | + $key = $handle->getKey(); |
| 45 | + $normkey = strtr( strtolower( "$namespace:$key" ), " ", "_" ); |
| 46 | + |
| 47 | + $index = self::singleton()->retrieve(); |
| 48 | + if ( isset( $index[$normkey] ) ) { |
| 49 | + return (array) $index[$normkey]; |
| 50 | + } else { |
| 51 | + return array(); |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + /** |
| 56 | + * @since 2012-01-14 |
| 57 | + * @return MessageGroup|null |
| 58 | + */ |
| 59 | + public static function getPrimaryGroupId( MessageHandle $handle ) { |
| 60 | + $groups = self::getGroupIds( $handle ); |
| 61 | + return count( $groups ) ? array_shift( $groups ) : null; |
| 62 | + } |
| 63 | + |
40 | 64 | /** @return array */ |
41 | 65 | abstract public function retrieve(); |
42 | 66 | abstract protected function store( array $array ); |
— | — | @@ -157,6 +181,9 @@ |
158 | 182 | * Storage on serialized file. |
159 | 183 | */ |
160 | 184 | class FileCachedMessageIndex extends MessageIndex { |
| 185 | + /// @var array |
| 186 | + protected $index; |
| 187 | + |
161 | 188 | protected $filename = 'translate_messageindex.ser'; |
162 | 189 | |
163 | 190 | /** @return array */ |
— | — | @@ -187,6 +214,9 @@ |
188 | 215 | protected $key = 'translate-messageindex'; |
189 | 216 | protected $cache; |
190 | 217 | |
| 218 | + /// @var array |
| 219 | + protected $index; |
| 220 | + |
191 | 221 | protected function __construct( array $params ) { |
192 | 222 | $this->cache = wfGetCache( CACHE_ANYTHING ); |
193 | 223 | } |
Index: trunk/extensions/Translate/utils/TranslationHelpers.php |
— | — | @@ -16,22 +16,16 @@ |
17 | 17 | */ |
18 | 18 | class TranslationHelpers { |
19 | 19 | /** |
20 | | - * Title of the message |
| 20 | + * @var MessageHandle |
| 21 | + * @since 2012-01-04 |
21 | 22 | */ |
22 | | - protected $title; |
| 23 | + protected $handle; |
23 | 24 | /** |
24 | | - * Name of the message without namespace or language code. |
25 | | - */ |
26 | | - protected $page; |
27 | | - /** |
28 | | - * The language we are translating into. |
29 | | - */ |
30 | | - protected $targetLanguage; |
31 | | - /** |
32 | 25 | * The group object of the message (or null if there isn't any) |
33 | 26 | * @var MessageGroup |
34 | 27 | */ |
35 | 28 | protected $group; |
| 29 | + |
36 | 30 | /** |
37 | 31 | * The current translation as a string. |
38 | 32 | */ |
— | — | @@ -51,45 +45,28 @@ |
52 | 46 | protected $editMode = 'true'; |
53 | 47 | |
54 | 48 | /** |
55 | | - * @param $title Title Title of a page that holds a translation. |
| 49 | + * @param $title Title: Title of a page that holds a translation. |
| 50 | + * @param $group String: Group id that should be used, otherwise autodetected from title. |
56 | 51 | */ |
57 | | - public function __construct( Title $title ) { |
58 | | - $this->title = $title; |
59 | | - $this->init(); |
| 52 | + public function __construct( Title $title, $groupId ) { |
| 53 | + $this->handle = new MessageHandle( $title ); |
| 54 | + $this->group = $this->getMessageGroup( $this->handle, $groupId ); |
60 | 55 | } |
61 | 56 | |
62 | 57 | /** |
63 | | - * Initializes member variables. |
64 | | - */ |
65 | | - protected function init() { |
66 | | - $title = $this->title; |
67 | | - list( $page, $code ) = TranslateEditAddons::figureMessage( $title ); |
68 | | - |
69 | | - $this->page = $page; |
70 | | - $this->targetLanguage = $code; |
71 | | - $this->group = self::getMessageGroup( $title->getNamespace(), $page ); |
72 | | - } |
73 | | - |
74 | | - /** |
75 | 58 | * Tries to determine to which group this message belongs. It tries to get |
76 | 59 | * group id from loadgroup GET-paramater, but fallbacks to messageIndex file |
77 | 60 | * if no valid group was provided. |
78 | | - * @param $namespace int The namespace where the page is. |
79 | | - * @param $key string The message key we are interested in. |
| 61 | + * |
80 | 62 | * @return MessageGroup which the key belongs to, or null. |
81 | 63 | */ |
82 | | - protected static function getMessageGroup( $namespace, $key ) { |
83 | | - global $wgRequest; |
| 64 | + protected function getMessageGroup( MessageHandle $handle, $groupId ) { |
| 65 | + $mg = MessageGroups::getGroup( $groupId ); |
84 | 66 | |
85 | | - $group = $wgRequest->getText( 'loadgroup', '' ); |
86 | | - $mg = MessageGroups::getGroup( $group ); |
87 | | - |
88 | | - # If we were not given group |
| 67 | + # If we were not given (a valid) group |
89 | 68 | if ( $mg === null ) { |
90 | | - $group = TranslateUtils::messageKeyToGroup( $namespace, $key ); |
91 | | - if ( $group ) { |
92 | | - $mg = MessageGroups::getGroup( $group ); |
93 | | - } |
| 69 | + $groupId = MessageIndex::getPrimaryGroupId( $handle ); |
| 70 | + $mg = MessageGroups::getGroup( $groupId ); |
94 | 71 | } |
95 | 72 | |
96 | 73 | return $mg; |
— | — | @@ -128,12 +105,14 @@ |
129 | 106 | return $this->definition; |
130 | 107 | } |
131 | 108 | |
132 | | - if ( $this->group === null ) { |
133 | | - return ''; |
| 109 | + $this->mustBeKnownMessage(); |
| 110 | + |
| 111 | + if ( method_exists( $this->group, 'getMessageContent' ) ) { |
| 112 | + $this->definition = $this->group->getMessageContent( $this->handle, $this->group->getSourceLanguage() ); |
| 113 | + } else { |
| 114 | + $this->definition = $this->group->getMessage( $this->handle->getKey(), $this->group->getSourceLanguage() ); |
134 | 115 | } |
135 | 116 | |
136 | | - $this->definition = $this->group->getMessage( $this->page, $this->group->getSourceLanguage() ); |
137 | | - |
138 | 117 | return $this->definition; |
139 | 118 | } |
140 | 119 | |
— | — | @@ -148,17 +127,18 @@ |
149 | 128 | } |
150 | 129 | |
151 | 130 | // Shorter names |
152 | | - $page = $this->page; |
153 | | - $code = $this->targetLanguage; |
| 131 | + $title = $this->handle->getTitle(); |
| 132 | + $page = $this->handle->getKey(); |
| 133 | + $code = $this->handle->getCode(); |
154 | 134 | $group = $this->group; |
155 | 135 | |
156 | 136 | // Try database first |
157 | 137 | $translation = TranslateUtils::getMessageContent( |
158 | | - $page, $code, $this->title->getNamespace() |
| 138 | + $page, $code, $title->getNamespace() |
159 | 139 | ); |
160 | 140 | |
161 | 141 | if ( $translation !== null ) { |
162 | | - if ( !TranslateEditAddons::hasFuzzyString( $translation ) && TranslateEditAddons::isFuzzy( $this->title ) ) { |
| 142 | + if ( !TranslateEditAddons::hasFuzzyString( $translation ) && TranslateEditAddons::isFuzzy( $title ) ) { |
163 | 143 | $translation = TRANSLATE_FUZZY . $translation; |
164 | 144 | } |
165 | 145 | } elseif ( $group && !$group instanceof FileBasedMessageGroup ) { |
— | — | @@ -184,10 +164,19 @@ |
185 | 165 | } |
186 | 166 | |
187 | 167 | /** |
188 | | - * Get target language code |
| 168 | + * Gets the linguistically correct language code for translation |
189 | 169 | */ |
190 | 170 | public function getTargetLanguage() { |
191 | | - return $this->targetLanguage; |
| 171 | + global $wgLanguageCode, $wgTranslateDocumentationLanguageCode; |
| 172 | + |
| 173 | + $code = $this->handle->getCode(); |
| 174 | + if ( !$code ) { |
| 175 | + $this->mustBeKnownMessage(); |
| 176 | + $code = $group->getSourceLanguage(); |
| 177 | + } |
| 178 | + if ( $code === $wgTranslateDocumentationLanguageCode ) { |
| 179 | + return $wgLanguageCode; |
| 180 | + } |
192 | 181 | } |
193 | 182 | |
194 | 183 | /** |
— | — | @@ -217,7 +206,11 @@ |
218 | 207 | |
219 | 208 | $boxes = array(); |
220 | 209 | foreach ( $all as $type => $cb ) { |
221 | | - $box = call_user_func( $cb ); |
| 210 | + try { |
| 211 | + $box = call_user_func( $cb ); |
| 212 | + } catch ( TranslationHelperExpection $e ) { |
| 213 | + $box = "<!-- Box $type not available: {$e->getMessage()} -->"; |
| 214 | + } |
222 | 215 | |
223 | 216 | if ( $box ) { |
224 | 217 | $boxes[$type] = $box; |
— | — | @@ -254,22 +247,17 @@ |
255 | 248 | * @return string Html snippet which contains the suggestions. |
256 | 249 | */ |
257 | 250 | protected function getTmBox( $serviceName, $config ) { |
258 | | - if ( !$this->targetLanguage ) { |
259 | | - return null; |
260 | | - } |
| 251 | + $this->mustHaveDefinition(); |
| 252 | + self::checkTranslationServiceFailure( $serviceName ); |
261 | 253 | |
262 | | - if ( strval( $this->getDefinition() ) === '' ) { |
263 | | - return null; |
| 254 | + // Needed data |
| 255 | + $page = $this->handle->getKey(); |
| 256 | + $code = $this->handle->getCode(); |
| 257 | + if ( !$code ) { |
| 258 | + $code = $this->group->getSourceLanguage(); |
264 | 259 | } |
265 | | - |
266 | | - if ( self::checkTranslationServiceFailure( $serviceName ) ) { |
267 | | - return null; |
268 | | - } |
269 | | - |
270 | | - // Needed data |
271 | | - $code = $this->targetLanguage; |
272 | 260 | $definition = $this->getDefinition(); |
273 | | - $ns = $this->title->getNsText(); |
| 261 | + $ns = $this->handle->getTitle()->getNsText(); |
274 | 262 | |
275 | 263 | // Fetch suggestions |
276 | 264 | $server = $config['server']; |
— | — | @@ -283,47 +271,46 @@ |
284 | 272 | // Parse suggestions, but limit to three (in case there would be more) |
285 | 273 | $boxes = array(); |
286 | 274 | |
287 | | - if ( $suggestions !== false ) { |
288 | | - $suggestions = FormatJson::decode( $suggestions, true ); |
| 275 | + if ( $suggestions === false ) { |
| 276 | + // Assume timeout |
| 277 | + self::reportTranslationServiceFailure( $serviceName ); |
| 278 | + } |
| 279 | + $suggestions = FormatJson::decode( $suggestions, true ); |
289 | 280 | |
290 | | - foreach ( $suggestions as $s ) { |
291 | | - // No use to suggest them what they are currently viewing |
292 | | - if ( $s['context'] === "$ns:{$this->page}" ) { |
293 | | - continue; |
294 | | - } |
| 281 | + foreach ( $suggestions as $s ) { |
| 282 | + // No use to suggest them what they are currently viewing |
| 283 | + if ( $s['context'] === "$ns:$page" ) { |
| 284 | + continue; |
| 285 | + } |
295 | 286 | |
296 | | - $accuracy = wfMsgHtml( 'translate-edit-tmmatch' , sprintf( '%.2f', $s['quality'] ) ); |
297 | | - $legend = array( $accuracy => array() ); |
| 287 | + $accuracy = wfMsgHtml( 'translate-edit-tmmatch' , sprintf( '%.2f', $s['quality'] ) ); |
| 288 | + $legend = array( $accuracy => array() ); |
298 | 289 | |
299 | | - $source_page = Title::newFromText( $s['context'] . "/$code" ); |
300 | | - if ( $source_page ) { |
301 | | - $legend[$accuracy][] = self::ajaxEditLink( $source_page, '•' ); |
302 | | - } |
| 290 | + $source_page = Title::newFromText( $s['context'] . "/$code" ); |
| 291 | + if ( $source_page ) { |
| 292 | + $legend[$accuracy][] = self::ajaxEditLink( $source_page, '•' ); |
| 293 | + } |
303 | 294 | |
304 | | - $text = $this->suggestionField( $s['target'] ); |
305 | | - $params = array( 'class' => 'mw-sp-translate-edit-tmsug', 'title' => $s['source'] ); |
| 295 | + $text = $this->suggestionField( $s['target'] ); |
| 296 | + $params = array( 'class' => 'mw-sp-translate-edit-tmsug', 'title' => $s['source'] ); |
306 | 297 | |
307 | | - if ( isset( $sugFields[$s['target']] ) ) { |
308 | | - $sugFields[$s['target']][2] = array_merge_recursive( $sugFields[$s['target']][2], $legend ); |
309 | | - } else { |
310 | | - $sugFields[$s['target']] = array( $text, $params, $legend ); |
311 | | - } |
| 298 | + if ( isset( $sugFields[$s['target']] ) ) { |
| 299 | + $sugFields[$s['target']][2] = array_merge_recursive( $sugFields[$s['target']][2], $legend ); |
| 300 | + } else { |
| 301 | + $sugFields[$s['target']] = array( $text, $params, $legend ); |
312 | 302 | } |
| 303 | + } |
313 | 304 | |
314 | | - foreach ( $sugFields as $field ) { |
315 | | - list( $text, $params, $label ) = $field; |
316 | | - $legend = array(); |
| 305 | + foreach ( $sugFields as $field ) { |
| 306 | + list( $text, $params, $label ) = $field; |
| 307 | + $legend = array(); |
317 | 308 | |
318 | | - foreach ( $label as $acc => $links ) { |
319 | | - $legend[] = $acc . ' ' . implode( " ", $links ); |
320 | | - } |
| 309 | + foreach ( $label as $acc => $links ) { |
| 310 | + $legend[] = $acc . ' ' . implode( " ", $links ); |
| 311 | + } |
321 | 312 | |
322 | | - $legend = implode( ' | ', $legend ); |
323 | | - $boxes[] = Html::rawElement( 'div', $params, self::legend( $legend ) . $text . self::clear() ) . "\n"; |
324 | | - } |
325 | | - } else { |
326 | | - // Assume timeout |
327 | | - self::reportTranslationServiceFailure( $serviceName ); |
| 313 | + $legend = implode( ' | ', $legend ); |
| 314 | + $boxes[] = Html::rawElement( 'div', $params, self::legend( $legend ) . $text . self::clear() ) . "\n"; |
328 | 315 | } |
329 | 316 | |
330 | 317 | $boxes = array_slice( $boxes, 0, 3 ); |
— | — | @@ -378,18 +365,17 @@ |
379 | 366 | protected function getGoogleSuggestion( $serviceName, $config ) { |
380 | 367 | global $wgMemc; |
381 | 368 | |
382 | | - if ( self::checkTranslationServiceFailure( $serviceName ) ) { |
383 | | - return null; |
384 | | - } |
| 369 | + $this->mustHaveDefinition(); |
| 370 | + self::checkTranslationServiceFailure( $serviceName ); |
385 | 371 | |
386 | | - $code = $this->targetLanguage; |
| 372 | + $code = $this->handle->getCode(); |
387 | 373 | $definition = trim( strval( $this->getDefinition() ) ); |
388 | 374 | $definition = self::wrapUntranslatable( $definition ); |
389 | 375 | |
390 | 376 | $memckey = wfMemckey( 'translate-tmsug-badcodes-' . $serviceName ); |
391 | 377 | $unsupported = $wgMemc->get( $memckey ); |
392 | 378 | |
393 | | - if ( $definition === '' || isset( $unsupported[$code] ) ) { |
| 379 | + if ( isset( $unsupported[$code] ) ) { |
394 | 380 | return null; |
395 | 381 | } |
396 | 382 | |
— | — | @@ -407,8 +393,6 @@ |
408 | 394 | if ( $json === false ) { |
409 | 395 | // Most likely a timeout or other general error |
410 | 396 | self::reportTranslationServiceFailure( $serviceName ); |
411 | | - |
412 | | - return null; |
413 | 397 | } elseif ( !is_object( $response ) ) { |
414 | 398 | error_log( __METHOD__ . ': Unable to parse reply: ' . strval( $json ) ); |
415 | 399 | return null; |
— | — | @@ -424,10 +408,9 @@ |
425 | 409 | $wgMemc->set( $memckey, $unsupported, 60 * 60 * 8 ); |
426 | 410 | } else { |
427 | 411 | // Unknown error, assume the worst |
428 | | - self::reportTranslationServiceFailure( $serviceName ); |
429 | 412 | wfWarn( __METHOD__ . "($serviceName): " . $response->responseDetails ); |
430 | 413 | error_log( __METHOD__ . "($serviceName): " . $response->responseDetails ); |
431 | | - return null; |
| 414 | + self::reportTranslationServiceFailure( $serviceName ); |
432 | 415 | } |
433 | 416 | |
434 | 417 | return null; |
— | — | @@ -457,18 +440,17 @@ |
458 | 441 | protected function getMicrosoftSuggestion( $serviceName, $config ) { |
459 | 442 | global $wgMemc; |
460 | 443 | |
461 | | - if ( self::checkTranslationServiceFailure( $serviceName ) ) { |
462 | | - return null; |
463 | | - } |
| 444 | + $this->mustHaveDefinition(); |
| 445 | + self::checkTranslationServiceFailure( $serviceName ); |
464 | 446 | |
465 | | - $code = $this->targetLanguage; |
| 447 | + $code = $this->handle->getCode(); |
466 | 448 | $definition = trim( strval( $this->getDefinition() ) ); |
467 | 449 | $definition = self::wrapUntranslatable( $definition ); |
468 | 450 | |
469 | 451 | $memckey = wfMemckey( 'translate-tmsug-badcodes-' . $serviceName ); |
470 | 452 | $unsupported = $wgMemc->get( $memckey ); |
471 | 453 | |
472 | | - if ( $definition === '' || isset( $unsupported[$code] ) ) { |
| 454 | + if ( isset( $unsupported[$code] ) ) { |
473 | 455 | return null; |
474 | 456 | } |
475 | 457 | |
— | — | @@ -514,7 +496,6 @@ |
515 | 497 | } |
516 | 498 | // Most likely a timeout or other general error |
517 | 499 | self::reportTranslationServiceFailure( $serviceName ); |
518 | | - return null; |
519 | 500 | } |
520 | 501 | |
521 | 502 | $ret = $req->getContent(); |
— | — | @@ -541,13 +522,11 @@ |
542 | 523 | protected function getApertiumSuggestion( $serviceName, $config ) { |
543 | 524 | global $wgMemc; |
544 | 525 | |
545 | | - if ( self::checkTranslationServiceFailure( $serviceName ) ) { |
546 | | - return null; |
547 | | - } |
| 526 | + self::checkTranslationServiceFailure( $serviceName ); |
548 | 527 | |
549 | | - $page = $this->page; |
550 | | - $code = $this->targetLanguage; |
551 | | - $ns = $this->title->getNamespace(); |
| 528 | + $page = $this->handle->getKey(); |
| 529 | + $code = $this->handle->getCode(); |
| 530 | + $ns = $this->handle->getTitle()->getNamespace(); |
552 | 531 | |
553 | 532 | $memckey = wfMemckey( 'translate-tmsug-pairs-' . $serviceName ); |
554 | 533 | $pairs = $wgMemc->get( $memckey ); |
— | — | @@ -560,7 +539,6 @@ |
561 | 540 | |
562 | 541 | if ( $json === false ) { |
563 | 542 | self::reportTranslationServiceFailure( $serviceName ); |
564 | | - return null; |
565 | 543 | } elseif ( !is_object( $response ) ) { |
566 | 544 | error_log( __METHOD__ . ': Unable to parse reply: ' . strval( $json ) ); |
567 | 545 | return null; |
— | — | @@ -614,7 +592,6 @@ |
615 | 593 | $response = FormatJson::decode( $json ); |
616 | 594 | if ( $json === false || !is_object( $response ) ) { |
617 | 595 | self::reportTranslationServiceFailure( $serviceName ); |
618 | | - break; // Too slow, back off |
619 | 596 | } elseif ( $response->responseStatus !== 200 ) { |
620 | 597 | error_log( __METHOD__ . " (HTTP {$response->responseStatus}) with ($serviceName ($candidate|$code)): " . $response->responseDetails ); |
621 | 598 | } else { |
— | — | @@ -637,10 +614,8 @@ |
638 | 615 | } |
639 | 616 | |
640 | 617 | public function getDefinitionBox() { |
641 | | - $en = strval( $this->getDefinition() ); |
642 | | - if ( $en === '' ) { |
643 | | - return null; |
644 | | - } |
| 618 | + $this->mustHaveDefinition(); |
| 619 | + $en = $this->getDefinition(); |
645 | 620 | |
646 | 621 | $linker = class_exists( 'DummyLinker' ) ? new DummyLinker : new Linker; |
647 | 622 | $title = $linker->link( |
— | — | @@ -649,7 +624,7 @@ |
650 | 625 | array(), |
651 | 626 | array( |
652 | 627 | 'group' => $this->group->getId(), |
653 | | - 'language' => $this->targetLanguage |
| 628 | + 'language' => $this->handle->getCode() |
654 | 629 | ) |
655 | 630 | ); |
656 | 631 | |
— | — | @@ -695,17 +670,15 @@ |
696 | 671 | } |
697 | 672 | |
698 | 673 | public function getCheckBox() { |
| 674 | + $this->mustBeKnownMessage(); |
| 675 | + |
699 | 676 | global $wgTranslateDocumentationLanguageCode; |
700 | 677 | |
701 | 678 | $placeholder = Html::element( 'div', array( 'class' => 'mw-translate-messagechecks' ) ); |
702 | 679 | |
703 | | - if ( $this->group === null ) { |
704 | | - return null; |
705 | | - } |
706 | | - |
707 | | - $page = $this->page; |
| 680 | + $page = $this->handle->getKey(); |
708 | 681 | $translation = $this->getTranslation(); |
709 | | - $code = $this->targetLanguage; |
| 682 | + $code = $this->handle->getCode(); |
710 | 683 | $en = $this->getDefinition(); |
711 | 684 | |
712 | 685 | if ( strval( $translation ) === '' ) { |
— | — | @@ -746,9 +719,9 @@ |
747 | 720 | public function getOtherLanguagesBox() { |
748 | 721 | global $wgLang; |
749 | 722 | |
750 | | - $code = $this->targetLanguage; |
751 | | - $page = $this->page; |
752 | | - $ns = $this->title->getNamespace(); |
| 723 | + $code = $this->handle->getCode(); |
| 724 | + $page = $this->handle->getKey(); |
| 725 | + $ns = $this->handle->getTitle()->getNamespace(); |
753 | 726 | |
754 | 727 | $boxes = array(); |
755 | 728 | foreach ( self::getFallbacks( $code ) as $fbcode ) { |
— | — | @@ -807,8 +780,8 @@ |
808 | 781 | return null; |
809 | 782 | } |
810 | 783 | |
811 | | - $page = $this->page; |
812 | | - $ns = $this->title->getNamespace(); |
| 784 | + $page = $this->handle->getKey(); |
| 785 | + $ns = $this->handle->getTitle()->getNamespace(); |
813 | 786 | |
814 | 787 | $title = Title::makeTitle( $ns, $page . '/' . $wgTranslateDocumentationLanguageCode ); |
815 | 788 | $edit = self::ajaxEditLink( $title, wfMsgHtml( 'translate-edit-contribute' ) ); |
— | — | @@ -848,7 +821,7 @@ |
849 | 822 | $ffs = $this->group->getFFS(); |
850 | 823 | if ( $ffs instanceof GettextFFS ) { |
851 | 824 | global $wgContLang; |
852 | | - $mykey = $wgContLang->lcfirst( $this->page ); |
| 825 | + $mykey = $wgContLang->lcfirst( $this->handle->getKey() ); |
853 | 826 | $data = $ffs->read( $this->group->getSourceLanguage() ); |
854 | 827 | $help = $data['TEMPLATE'][$mykey]['comments']; |
855 | 828 | // Do not display an empty comment. That's no help and takes up unnecessary space. |
— | — | @@ -881,21 +854,24 @@ |
882 | 855 | } |
883 | 856 | |
884 | 857 | protected function getPageDiff() { |
885 | | - if ( $this->group instanceof WikiPageMessageGroup || $this->group === null ) { |
| 858 | + $this->mustBeKnownMessage(); |
| 859 | + |
| 860 | + $group = $this->group; |
| 861 | + $title = $this->handle->getTitle(); |
| 862 | + $key = $this->handle->getKey(); |
| 863 | + |
| 864 | + if ( $group instanceof WikiPageMessageGroup ) { |
886 | 865 | return null; |
887 | 866 | } |
888 | 867 | |
889 | | - // Shortcuts |
890 | | - $key = $this->page; |
891 | | - |
892 | | - $definitionTitle = Title::makeTitleSafe( $this->title->getNamespace(), "$key/en" ); |
| 868 | + $definitionTitle = Title::makeTitleSafe( $title->getNamespace(), "$key/en" ); |
893 | 869 | if ( !$definitionTitle || !$definitionTitle->exists() ) { |
894 | 870 | return null; |
895 | 871 | } |
896 | 872 | |
897 | 873 | $db = wfGetDB( DB_MASTER ); |
898 | 874 | $conds = array( |
899 | | - 'rt_page' => $this->title->getArticleId(), |
| 875 | + 'rt_page' => $title->getArticleId(), |
900 | 876 | 'rt_type' => RevTag::getType( 'tp:transver' ), |
901 | 877 | ); |
902 | 878 | $options = array( |
— | — | @@ -934,19 +910,21 @@ |
935 | 911 | } |
936 | 912 | |
937 | 913 | protected function getTranslationPageDiff() { |
| 914 | + |
938 | 915 | global $wgEnablePageTranslation; |
939 | 916 | |
940 | 917 | if ( !$wgEnablePageTranslation ) { |
941 | 918 | return null; |
942 | 919 | } |
943 | 920 | |
| 921 | + $this->mustBeKnownMessage(); |
944 | 922 | if ( !$this->group instanceof WikiPageMessageGroup ) { |
945 | 923 | return null; |
946 | 924 | } |
947 | 925 | |
948 | 926 | // Shortcuts |
949 | | - $code = $this->targetLanguage; |
950 | | - $key = $this->page; |
| 927 | + $code = $this->handle->getCode(); |
| 928 | + $key = $this->handle->getKey(); |
951 | 929 | |
952 | 930 | // TODO: encapsulate somewhere |
953 | 931 | $page = TranslatablePage::newFromTitle( $this->group->getTitle() ); |
— | — | @@ -987,7 +965,7 @@ |
988 | 966 | |
989 | 967 | protected function getLastDiff() { |
990 | 968 | // Shortcuts |
991 | | - $title = $this->title; |
| 969 | + $title = $this->handle->getTitle(); |
992 | 970 | $latestRevId = $title->getLatestRevID(); |
993 | 971 | $previousRevId = $title->getPreviousRevisionID( $latestRevId ); |
994 | 972 | |
— | — | @@ -1002,7 +980,7 @@ |
1003 | 981 | if ( $previous !== $latest ) { |
1004 | 982 | $diff = new DifferenceEngine; |
1005 | 983 | if ( method_exists( 'DifferenceEngine', 'setTextLanguage' ) ) { |
1006 | | - $diff->setTextLanguage( $this->targetLanguage ); |
| 984 | + $diff->setTextLanguage( $this->getTargetLanguage() ); |
1007 | 985 | } |
1008 | 986 | $diff->setText( $previous, $latest ); |
1009 | 987 | $diff->setReducedLineNumbers(); |
— | — | @@ -1032,7 +1010,7 @@ |
1033 | 1011 | $text = wfMessage( 'translate-dynagroup-last', $user )->escaped(); |
1034 | 1012 | } |
1035 | 1013 | } |
1036 | | - |
| 1014 | + |
1037 | 1015 | return TranslateUtils::fieldset( $text, $diffText, array( 'class' => 'mw-sp-translate-latestchange' ) ); |
1038 | 1016 | } |
1039 | 1017 | |
— | — | @@ -1144,13 +1122,14 @@ |
1145 | 1123 | * @return null|string |
1146 | 1124 | */ |
1147 | 1125 | public function getLazySuggestionBox() { |
1148 | | - if ( $this->group === null || !$this->targetLanguage ) { |
| 1126 | + $this->mustBeKnownMessage(); |
| 1127 | + if ( !$this->handle->getCode() ) { |
1149 | 1128 | return null; |
1150 | 1129 | } |
1151 | 1130 | |
1152 | 1131 | $url = SpecialPage::getTitleFor( 'Translate', 'editpage' )->getLocalUrl( array( |
1153 | 1132 | 'suggestions' => 'only', |
1154 | | - 'page' => $this->title->getPrefixedDbKey(), |
| 1133 | + 'page' => $this->handle->getTitle()->getPrefixedDbKey(), |
1155 | 1134 | 'loadgroup' => $this->group->getId(), |
1156 | 1135 | ) ); |
1157 | 1136 | $url = Xml::encodeJsVar( $url ); |
— | — | @@ -1167,22 +1146,22 @@ |
1168 | 1147 | * @return string |
1169 | 1148 | */ |
1170 | 1149 | public function dialogID() { |
1171 | | - $hash = sha1( $this->title->getPrefixedDbKey() ); |
| 1150 | + $hash = sha1( $this->handle->getTitle()->getPrefixedDbKey() ); |
1172 | 1151 | return substr( $hash, 0, 4 ); |
1173 | 1152 | } |
1174 | 1153 | |
1175 | 1154 | /** |
1176 | | - * @param $source |
1177 | | - * @param $lang |
| 1155 | + * @param $source jQuery selector for element containing the source |
| 1156 | + * @param $lang Language code or object |
1178 | 1157 | * @return string |
1179 | 1158 | */ |
1180 | | - public function adder( $source, $lang = null ) { |
| 1159 | + public function adder( $source, $lang ) { |
1181 | 1160 | if ( !$this->editMode ) { |
1182 | 1161 | return ''; |
1183 | 1162 | } |
1184 | 1163 | $target = self::jQueryPathId( $this->getTextareaId() ); |
1185 | 1164 | $source = self::jQueryPathId( $source ); |
1186 | | - $dir = wfGetLangObj( $lang ? $lang : $this->targetLanguage )->getDir(); |
| 1165 | + $dir = wfGetLangObj( $lang )->getDir(); |
1187 | 1166 | $params = array( |
1188 | 1167 | 'onclick' => "jQuery($target).val(jQuery($source).text()).focus(); return false;", |
1189 | 1168 | 'href' => '#', |
— | — | @@ -1209,15 +1188,17 @@ |
1210 | 1189 | public function suggestionField( $text ) { |
1211 | 1190 | static $counter = 0; |
1212 | 1191 | |
| 1192 | + $code = $this->getTargetLanguage(); |
| 1193 | + |
1213 | 1194 | $counter++; |
1214 | 1195 | $dialogID = $this->dialogID(); |
1215 | 1196 | $id = Sanitizer::escapeId( "tmsug-$dialogID-$counter" ); |
1216 | | - $contents = Html::rawElement( 'div', array( 'lang' => $this->targetLanguage, |
1217 | | - 'dir' => Language::factory( $this->targetLanguage )->getDir() ), |
| 1197 | + $contents = Html::rawElement( 'div', array( 'lang' => $code, |
| 1198 | + 'dir' => Language::factory( $code )->getDir() ), |
1218 | 1199 | TranslateUtils::convertWhiteSpaceToHTML( $text ) ); |
1219 | 1200 | $contents .= $this->wrapInsert( $id, $text ); |
1220 | 1201 | |
1221 | | - return $this->adder( $id ) . "\n" . $contents; |
| 1202 | + return $this->adder( $id, $code ) . "\n" . $contents; |
1222 | 1203 | } |
1223 | 1204 | |
1224 | 1205 | /** |
— | — | @@ -1227,14 +1208,14 @@ |
1228 | 1209 | * @return link |
1229 | 1210 | */ |
1230 | 1211 | public static function ajaxEditLink( $target, $text ) { |
1231 | | - list( $page, ) = TranslateEditAddons::figureMessage( $target ); |
1232 | | - $group = TranslateUtils::messageKeyToGroup( $target->getNamespace(), $page ); |
| 1212 | + $handle = new MessageHandle( $target ); |
| 1213 | + $groupId = MessageIndex::getPrimaryGroupId( $handle ); |
1233 | 1214 | |
1234 | 1215 | $params = array(); |
1235 | 1216 | $params['action'] = 'edit'; |
1236 | | - $params['loadgroup'] = $group; |
| 1217 | + $params['loadgroup'] = $groupId; |
1237 | 1218 | |
1238 | | - $jsEdit = TranslationEditPage::jsEdit( $target, $group ); |
| 1219 | + $jsEdit = TranslationEditPage::jsEdit( $target, $groupId ); |
1239 | 1220 | |
1240 | 1221 | $linker = class_exists( 'DummyLinker' ) ? new DummyLinker() : new Linker(); |
1241 | 1222 | return $linker->link( $target, $text, $jsEdit, $params ); |
— | — | @@ -1287,7 +1268,9 @@ |
1288 | 1269 | return false; |
1289 | 1270 | } |
1290 | 1271 | |
1291 | | - return $count >= self::$serviceFailureCount; |
| 1272 | + if ( $count >= self::$serviceFailureCount ) { |
| 1273 | + throw new TranslationHelperExpection( "web service $service is temporarily disabled" ); |
| 1274 | + } |
1292 | 1275 | } |
1293 | 1276 | |
1294 | 1277 | /** |
— | — | @@ -1314,11 +1297,10 @@ |
1315 | 1298 | } elseif ( $count > self::$serviceFailureCount ) { |
1316 | 1299 | error_log( "Translation service $service still suspended" ); |
1317 | 1300 | } |
| 1301 | + |
| 1302 | + throw new TranslationHelperExpection( "web service $service failed to provide valid response" ); |
1318 | 1303 | } |
1319 | 1304 | |
1320 | | - /** |
1321 | | - * @param $out OutputPage |
1322 | | - */ |
1323 | 1305 | public static function addModules( OutputPage $out ) { |
1324 | 1306 | $out->addModules( 'ext.translate.quickedit' ); |
1325 | 1307 | |
— | — | @@ -1329,4 +1311,28 @@ |
1330 | 1312 | $diff = new DifferenceEngine; |
1331 | 1313 | $diff->showDiffStyle(); |
1332 | 1314 | } |
| 1315 | + |
| 1316 | + /// @since 2012-01-04 |
| 1317 | + protected function mustBeKnownMessage() { |
| 1318 | + if ( !$this->group ) { |
| 1319 | + throw new TranslationHelperExpection( 'unknown group' ); |
| 1320 | + } |
| 1321 | + } |
| 1322 | + /// @since 2012-01-04 |
| 1323 | + protected function mustBeTranslation() { |
| 1324 | + if ( !$this->handle->getCode() ) { |
| 1325 | + throw new TranslationHelperExpection( 'editing source language' ); |
| 1326 | + } |
| 1327 | + } |
| 1328 | + |
| 1329 | + /// @since 2012-01-04 |
| 1330 | + protected function mustHaveDefinition() { |
| 1331 | + if ( strval( $this->getDefinition() ) === '' ) { |
| 1332 | + throw new TranslationHelperExpection( 'message does not have definition' ); |
| 1333 | + } |
| 1334 | + } |
| 1335 | + |
1333 | 1336 | } |
| 1337 | + |
| 1338 | +/// @since 2012-01-04 |
| 1339 | +class TranslationHelperExpection extends MWException {} |
Index: trunk/extensions/Translate/utils/TranslationEditPage.php |
— | — | @@ -60,12 +60,13 @@ |
61 | 61 | * disabled all other output. |
62 | 62 | */ |
63 | 63 | public function execute() { |
64 | | - global $wgOut, $wgServer, $wgScriptPath, $wgUser; |
| 64 | + global $wgOut, $wgServer, $wgScriptPath, $wgUser, $wgRequest; |
65 | 65 | |
66 | 66 | $wgOut->disable(); |
67 | 67 | |
68 | 68 | $data = $this->getEditInfo(); |
69 | | - $helpers = new TranslationHelpers( $this->getTitle() ); |
| 69 | + $groupId = $wgRequest->getText( 'loadgroup', '' ); |
| 70 | + $helpers = new TranslationHelpers( $this->getTitle(), $groupId ); |
70 | 71 | |
71 | 72 | $id = "tm-target-{$helpers->dialogID()}"; |
72 | 73 | $helpers->setTextareaId( $id ); |