Index: trunk/extensions/Translate/Message.php |
— | — | @@ -1,256 +1,13 @@ |
2 | 2 | <?php |
3 | | -if ( !defined( 'MEDIAWIKI' ) ) die(); |
4 | | -/** |
5 | | - * An extension to ease the translation of Mediawiki |
6 | | - * |
7 | | - * @addtogroup Extensions |
8 | | - * |
9 | | - * @author Niklas Laxström |
10 | | - * @copyright Copyright © 2007-2008, Niklas Laxström |
11 | | - * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
12 | | - */ |
13 | 3 | |
| 4 | +abstract class TMessage { |
| 5 | + protected $key; |
| 6 | + protected $definition; |
14 | 7 | |
15 | | -/** |
16 | | - * MessageCollection is a collection of TMessages. It supports array accces of |
17 | | - * TMessage object by message key. One collection can only have items for one |
18 | | - * translation target language. |
19 | | - */ |
20 | | -class MessageCollection implements Iterator, ArrayAccess, Countable { |
21 | 8 | /** |
22 | | - * Information of what type of MessageCollection this is. |
23 | | - */ |
24 | | - public $code = null; |
25 | | - |
26 | | - /** |
27 | | - * Messages are stored in an array. |
28 | | - */ |
29 | | - private $messages = array(); |
30 | | - |
31 | | - /** |
32 | | - * Creates new empty messages collection. |
33 | | - * |
34 | | - * @param $code Language code |
35 | | - */ |
36 | | - public function __construct( $code ) { |
37 | | - $this->code = $code; |
38 | | - } |
39 | | - |
40 | | - public function __clone() { |
41 | | - foreach ( $this->messages as $key => $obj ) { |
42 | | - $this->messages[$key] = clone $obj; |
43 | | - } |
44 | | - } |
45 | | - |
46 | | - /* Iterator methods */ |
47 | | - public function rewind() { |
48 | | - reset( $this->messages ); |
49 | | - } |
50 | | - |
51 | | - public function current() { |
52 | | - $messages = current( $this->messages ); |
53 | | - return $messages; |
54 | | - } |
55 | | - |
56 | | - public function key() { |
57 | | - $messages = key( $this->messages ); |
58 | | - return $messages; |
59 | | - } |
60 | | - |
61 | | - public function next() { |
62 | | - $messages = next( $this->messages ); |
63 | | - return $messages; |
64 | | - } |
65 | | - |
66 | | - public function valid() { |
67 | | - $messages = $this->current() !== false; |
68 | | - return $messages; |
69 | | - } |
70 | | - |
71 | | - /* ArrayAccess methods */ |
72 | | - public function offsetExists( $offset ) { |
73 | | - return isset( $this->messages[$offset] ); |
74 | | - } |
75 | | - |
76 | | - public function offsetGet( $offset ) { |
77 | | - return $this->messages[$offset]; |
78 | | - } |
79 | | - |
80 | | - public function offsetSet( $offset, $value ) { |
81 | | - if ( !$value instanceof TMessage ) { |
82 | | - throw new MWException( __METHOD__ . ": Trying to set member to invalid type" ); |
83 | | - } |
84 | | - $this->messages[$offset] = $value; |
85 | | - } |
86 | | - |
87 | | - public function offsetUnset( $offset ) { |
88 | | - unset( $this->messages[$offset] ); |
89 | | - } |
90 | | - |
91 | | - /* Countable methods */ |
92 | | - /** |
93 | | - * Counts the number of items in this collection. |
94 | | - * |
95 | | - * @return Integer count of items. |
96 | | - */ |
97 | | - public function count() { |
98 | | - return count( $this->messages ); |
99 | | - } |
100 | | - |
101 | | - |
102 | | - /** |
103 | | - * Adds new TMessage object to collection. |
104 | | - */ |
105 | | - public function add( TMessage $message ) { |
106 | | - $this->messages[$message->key] = $message; |
107 | | - } |
108 | | - |
109 | | - /** |
110 | | - * Adds array of TMessages to this collection. |
111 | | - * |
112 | | - * @param $messages Array of TMessage objects. |
113 | | - * @throws MWException |
114 | | - */ |
115 | | - public function addMany( array $messages ) { |
116 | | - foreach ( $messages as $message ) { |
117 | | - if ( !$message instanceof TMessage ) { |
118 | | - throw new MWException( __METHOD__ . ": Array contains something else than TMessage" ); |
119 | | - } |
120 | | - $this->messages[$message->key] = $message; |
121 | | - } |
122 | | - } |
123 | | - |
124 | | - /** |
125 | | - * Provides an array of keys for safe iteration. |
126 | | - * |
127 | | - * @return Array of string keys. |
128 | | - */ |
129 | | - public function keys() { |
130 | | - return array_keys( $this->messages ); |
131 | | - } |
132 | | - |
133 | | - /** |
134 | | - * Does array_slice to the messages. |
135 | | - * |
136 | | - * @param $offset Starting offset. |
137 | | - * @param $count Numer of items to slice. |
138 | | - */ |
139 | | - public function slice( $offset, $count ) { |
140 | | - $this->messages = array_slice( $this->messages, $offset, $count ); |
141 | | - } |
142 | | - |
143 | | - /** |
144 | | - * PHP function array_intersect_key doesn't seem to like object-as-arrays, so |
145 | | - * have to do provide some way to do it. Does not change object state. |
146 | | - * |
147 | | - * @param $array List of keys for messages that should be returned. |
148 | | - * @return New MessageCollection. |
149 | | - */ |
150 | | - public function intersect_key( Array $array ) { |
151 | | - $collection = new MessageCollection( $this->code ); |
152 | | - $collection->addMany( array_intersect_key( $this->messages, $array ) ); |
153 | | - return $collection; |
154 | | - } |
155 | | - |
156 | | - /* Fail fast */ |
157 | | - public function __get( $name ) { |
158 | | - throw new MWException( __METHOD__ . ": Trying to access unknown property $name" ); |
159 | | - } |
160 | | - |
161 | | - /* Fail fast */ |
162 | | - public function __set( $name, $value ) { |
163 | | - throw new MWException( __METHOD__ . ": Trying to modify unknown property $name" ); |
164 | | - } |
165 | | - |
166 | | - public function getAuthors() { |
167 | | - global $wgTranslateFuzzyBotName; |
168 | | - |
169 | | - $authors = array(); |
170 | | - foreach ( $this->keys() as $key ) { |
171 | | - // Check if there is authors |
172 | | - $_authors = $this->messages[$key]->authors; |
173 | | - if ( !count( $_authors ) ) continue; |
174 | | - |
175 | | - foreach ( $_authors as $author ) { |
176 | | - if ( !isset( $authors[$author] ) ) { |
177 | | - $authors[$author] = 1; |
178 | | - } else { |
179 | | - $authors[$author]++; |
180 | | - } |
181 | | - } |
182 | | - } |
183 | | - |
184 | | - arsort( $authors, SORT_NUMERIC ); |
185 | | - foreach ( $authors as $author => $edits ) { |
186 | | - if ( $author !== $wgTranslateFuzzyBotName ) { |
187 | | - $filteredAuthors[] = $author; |
188 | | - } |
189 | | - } |
190 | | - return isset( $filteredAuthors ) ? $filteredAuthors : array(); |
191 | | - } |
192 | | - |
193 | | - /** |
194 | | - * Filters messages based on some condition. |
195 | | - * |
196 | | - * @param $type Any accessible value of TMessage. |
197 | | - * @param $condition What the value is compared to. |
198 | | - */ |
199 | | - public function filter( $type, $condition = true ) { |
200 | | - foreach ( $this->keys() as $key ) { |
201 | | - if ( $this->messages[$key]->$type == $condition ) { |
202 | | - unset( $this->messages[$key] ); |
203 | | - } |
204 | | - } |
205 | | - } |
206 | | - |
207 | | -} |
208 | | - |
209 | | -class TMessage { |
210 | | - /** |
211 | | - * String that uniquely identifies this message. |
212 | | - */ |
213 | | - public $key = null; |
214 | | - |
215 | | - /** |
216 | | - * The definition of this message - usually in English. |
217 | | - */ |
218 | | - public $definition = null; |
219 | | - |
220 | | - // Following properties are lazy declared to save memory |
221 | | - |
222 | | - /** |
223 | | - * Authors who have taken part in translating this message. |
224 | | - */ |
225 | | - // protected $authors; |
226 | | - |
227 | | - /** |
228 | | - * External translation. |
229 | | - */ |
230 | | - // protected $infile = null; |
231 | | - |
232 | | - /** |
233 | | - * Translation in local database, may differ from above. |
234 | | - */ |
235 | | - // private $database = null; |
236 | | - |
237 | | - // Values that can be accessed with $message->value syntax |
238 | | - protected static $callable = array( |
239 | | - // Basic values |
240 | | - 'infile', 'database', 'optional', |
241 | | - // Derived values |
242 | | - 'authors', 'changed', 'translated', 'translation', 'fuzzy', |
243 | | - ); |
244 | | - |
245 | | - protected static $writable = array( |
246 | | - 'infile', 'database', 'optional', |
247 | | - // Ugly.. maybe I'm trying to be to clever here |
248 | | - 'authors', |
249 | | - ); |
250 | | - |
251 | | - /** |
252 | 9 | * Creates new message object. |
253 | 10 | * |
254 | | - * @param $key Uniquer key identifying this message. |
| 11 | + * @param $key Unique key identifying this message. |
255 | 12 | * @param $definition The authoritave definition of this message. |
256 | 13 | */ |
257 | 14 | public function __construct( $key, $definition ) { |
— | — | @@ -258,89 +15,61 @@ |
259 | 16 | $this->definition = $definition; |
260 | 17 | } |
261 | 18 | |
262 | | - // Getters for basic values |
263 | 19 | public function key() { return $this->key; } |
264 | 20 | public function definition() { return $this->definition; } |
| 21 | + abstract public function translation(); |
| 22 | +} |
265 | 23 | |
266 | | - public function infile() { return @$this->infile; } |
267 | | - public function database() { return @$this->database; } |
| 24 | +class ThinMessage extends TMessage { |
| 25 | + private $infile; |
| 26 | + private $row; |
| 27 | + private $tags = array(); |
268 | 28 | |
269 | | - public function optional() { return !!@$this->optional; } |
270 | | - |
271 | | - // Getters for derived values |
272 | | - /** Returns authors added for this message. */ |
273 | | - public function authors() { |
274 | | - return @$this->authors ? $this->authors : array(); |
| 29 | + public function setInfile( $text ) { |
| 30 | + $this->infile = $text; |
275 | 31 | } |
276 | 32 | |
277 | | - /** Determines if this message has uncommitted changes. */ |
278 | | - public function changed() { |
279 | | - return @$this->database !== null && ( @$this->infile !== @$this->database ); |
| 33 | + public function setRow( $row ) { |
| 34 | + $this->row = $row; |
280 | 35 | } |
281 | 36 | |
282 | | - /** |
283 | | - * Determies if this message has a proper translation. |
284 | | - * To check if message has translation at all, use translation !== null |
285 | | - */ |
286 | | - public function translated() { |
287 | | - if ( @$this->translation === null || $this->fuzzy() ) return false; |
288 | | - return true; |
| 37 | + public function setTag( $tag ) { |
| 38 | + $this->tags[] = $tag; |
289 | 39 | } |
290 | 40 | |
291 | | - /** |
292 | | - * Returns the current translation of message. Translation in database are |
293 | | - * preferred over those in source files. |
294 | | - * |
295 | | - * @return Translated string or null if there isn't translation. |
296 | | - */ |
| 41 | + |
| 42 | + public function key() { |
| 43 | + return $this->key; |
| 44 | + } |
| 45 | + public function definition() { |
| 46 | + return $this->definition; |
| 47 | + } |
297 | 48 | public function translation() { |
298 | | - return ( @$this->database !== null ) ? @$this->database : @$this->infile; |
| 49 | + if ( !isset($this->row) ) return null; |
| 50 | + return Revision::getRevisionText( $this->row ); |
299 | 51 | } |
300 | | - |
301 | | - /** |
302 | | - * Determines if the current translation in database (if any) is marked as |
303 | | - * fuzzy. |
304 | | - * |
305 | | - * @return true or false |
306 | | - */ |
307 | | - public function fuzzy() { |
308 | | - if ( @$this->translation !== null ) { |
309 | | - return strpos( $this->translation, TRANSLATE_FUZZY ) !== false; |
310 | | - } else { |
311 | | - return false; |
312 | | - } |
| 52 | + public function author() { |
| 53 | + if ( !isset($this->row) ) return null; |
| 54 | + return $this->row->rev_user_text; |
313 | 55 | } |
314 | 56 | |
315 | | - // Complex setters |
316 | | - public function addAuthor( $author ) { |
317 | | - $authors = $this->authors(); |
318 | | - $authors[] = $author; |
319 | | - $this->authors = $authors; |
| 57 | + public function infile() { |
| 58 | + if ( !isset($this->infile) ) return null; |
| 59 | + return $this->infile; |
320 | 60 | } |
321 | 61 | |
322 | | - // Code for PHP syntax magic to hide the difference between functions and values |
323 | | - public function __get( $name ) { |
324 | | - if ( in_array( $name, self::$callable ) ) { |
325 | | - return $this->$name(); |
326 | | - } |
327 | | - throw new MWException( __METHOD__ . ": Trying to access unknown property $name" ); |
| 62 | + public function hasTag( $tag ) { |
| 63 | + return in_array( $tag, $this->tags, true ); |
328 | 64 | } |
| 65 | +} |
329 | 66 | |
330 | | - public function __set( $name, $value ) { |
331 | | - if ( in_array( $name, self::$writable ) ) { |
332 | | - if ( gettype( $this->$name ) === gettype( $value ) || $this->$name === null && is_string( $value ) ) { |
333 | | - $this->$name = $value; |
334 | | - } else { |
335 | | - $type = gettype( $value ); |
336 | | - throw new MWException( __METHOD__ . ": Trying to set the value of property $name to illegal data type $type" ); |
337 | | - } |
338 | | - } else { |
339 | | - throw new MWException( __METHOD__ . ": Trying to set unknown property $name with value $value" ); |
340 | | - } |
| 67 | +class FatMessage extends TMessage { |
| 68 | + protected $translation = null; |
| 69 | + public function setTranslation( $text ) { |
| 70 | + $this->translation = $text; |
341 | 71 | } |
342 | 72 | |
343 | | - public function __isset( $name ) { |
344 | | - return @$this->$name !== null; |
| 73 | + public function translation() { |
| 74 | + return $this->translation; |
345 | 75 | } |
346 | | - |
347 | | -} |
| 76 | +} |
\ No newline at end of file |
Index: trunk/extensions/Translate/MessageGroups.php |
— | — | @@ -157,21 +157,6 @@ |
158 | 158 | private $messages = array(); |
159 | 159 | |
160 | 160 | /** |
161 | | - * In this function message group should add translations from the stored file |
162 | | - * for language code $code and it's fallback language, if used. |
163 | | - * |
164 | | - * @param $messages MessageCollection |
165 | | - */ |
166 | | - function fill( MessageCollection $messages ) { |
167 | | - $cache = $this->load( $messages->code ); |
168 | | - foreach ( $messages->keys() as $key ) { |
169 | | - if ( isset( $cache[$key] ) ) { |
170 | | - $messages[$key]->infile = $cache[$key]; |
171 | | - } |
172 | | - } |
173 | | - } |
174 | | - |
175 | | - /** |
176 | 161 | * Returns path to the file where translation of language code $code are. |
177 | 162 | * |
178 | 163 | * @return Path to the file or false if not applicable. |
— | — | @@ -193,7 +178,6 @@ |
194 | 179 | * group only. |
195 | 180 | */ |
196 | 181 | public function initCollection( $code, $unique = false ) { |
197 | | - $collection = new MessageCollection( $code ); |
198 | 182 | |
199 | 183 | if ( !$unique ) { |
200 | 184 | $definitions = $this->getDefinitions(); |
— | — | @@ -201,31 +185,16 @@ |
202 | 186 | $definitions = $this->getUniqueDefinitions(); |
203 | 187 | } |
204 | 188 | |
205 | | - foreach ( $definitions as $key => $definition ) { |
206 | | - $collection->add( new TMessage( $key, $definition ) ); |
207 | | - } |
| 189 | + $defs = new MessageDefinitions( $this->namespaces[0], $definitions ); |
| 190 | + $collection = MessageCollection::newFromDefinitions( $defs, $code ); |
208 | 191 | |
209 | 192 | $bools = $this->getBools(); |
210 | | - foreach ( $bools['optional'] as $key ) { |
211 | | - if ( isset( $collection[$key] ) ) { |
212 | | - $collection[$key]->optional = true; |
213 | | - } |
214 | | - } |
| 193 | + $collection->setTags( 'ignored', $bools['ignored'] ); |
| 194 | + $collection->setTags( 'optional', $bools['optional'] ); |
215 | 195 | |
216 | | - foreach ( $bools['ignored'] as $key ) { |
217 | | - if ( isset( $collection[$key] ) ) { |
218 | | - unset( $collection[$key] ); |
219 | | - } |
220 | | - } |
221 | | - |
222 | 196 | return $collection; |
223 | 197 | } |
224 | 198 | |
225 | | - public function fillCollection( MessageCollection $collection ) { |
226 | | - TranslateUtils::fillContents( $collection, $this->namespaces ); |
227 | | - $this->fill( $collection ); |
228 | | - } |
229 | | - |
230 | 199 | public function __construct() { |
231 | 200 | $this->mangler = StringMatcher::emptyMatcher(); |
232 | 201 | } |
— | — | @@ -554,10 +523,6 @@ |
555 | 524 | $this->source = $source; |
556 | 525 | } |
557 | 526 | |
558 | | - public function fill( MessageCollection $messages ) { |
559 | | - return; // no-op |
560 | | - } |
561 | | - |
562 | 527 | /* Fetch definitions from database */ |
563 | 528 | public function getDefinitions() { |
564 | 529 | $definitions = array(); |
— | — | @@ -593,6 +558,8 @@ |
594 | 559 | } |
595 | 560 | |
596 | 561 | class WikiPageMessageGroup extends WikiMessageGroup { |
| 562 | + protected $type = 'mediawiki'; |
| 563 | + |
597 | 564 | public $title; |
598 | 565 | |
599 | 566 | public function __construct( $id, $source ) { |
— | — | @@ -631,6 +598,7 @@ |
632 | 599 | |
633 | 600 | public function load( $code ) { |
634 | 601 | if ( $code === 'en' ) return $this->getDefinitions(); |
| 602 | + else return array(); |
635 | 603 | } |
636 | 604 | |
637 | 605 | /** |
— | — | @@ -651,37 +619,6 @@ |
652 | 620 | if ( !$rev ) return null; |
653 | 621 | return $rev->getText(); |
654 | 622 | } |
655 | | - |
656 | | - public function fillCollection( MessageCollection $messages ) { |
657 | | - parent::fillCollection( $messages ); |
658 | | - $page = TranslatablePage::newFromTitle( $this->title ); |
659 | | - $markedRevs = $page->getMarkedRevs( 'tp:mark' ); |
660 | | - |
661 | | - foreach ( $messages as $key => $m ) { |
662 | | - $rev = $page->getTransrev( $key .'/' . $messages->code ); |
663 | | - if ( $rev === false ) { |
664 | | - if ( !$m->database === null ) { |
665 | | - //TODO: fixme, ugly ugly ugly |
666 | | - $m->database = TRANSLATE_FUZZY . $m->database; |
667 | | - } |
668 | | - continue; |
669 | | - } |
670 | | - foreach ( $markedRevs as $r ) { |
671 | | - if ( $rev === $r->rt_revision ) break; |
672 | | - $changed = explode( '|', unserialize($r->rt_value) ); |
673 | | - |
674 | | - // Get a suitable section key |
675 | | - $parts = explode( '/', $key ); |
676 | | - $ikey = $parts[count($parts)-1]; |
677 | | - |
678 | | - // If the section was changed, reduce the score |
679 | | - if ( in_array($ikey, $changed, true) ) { |
680 | | - $m->database = TRANSLATE_FUZZY . $m->database; |
681 | | - continue 2; |
682 | | - } |
683 | | - } |
684 | | - } |
685 | | - } |
686 | 623 | } |
687 | 624 | |
688 | 625 | class MessageGroups { |
Index: trunk/extensions/Translate/tag/RenderJob.php |
— | — | @@ -35,9 +35,13 @@ |
36 | 36 | |
37 | 37 | // Return the actual translation page... |
38 | 38 | $page = TranslatablePage::isTranslationPage( $title ); |
| 39 | + if ( $page ) { |
| 40 | + var_dump( $params ); |
| 41 | + throw new MWException( "Oops, this should not happen!"); |
| 42 | + } |
| 43 | + |
39 | 44 | $group = MessageGroups::getGroup( "page|$key" ); |
40 | 45 | $collection = $group->initCollection( $code ); |
41 | | - $group->fillCollection( $collection ); |
42 | 46 | |
43 | 47 | // Muck up the text |
44 | 48 | $text = $page->getParse()->getTranslationPageText( $collection ); |
Index: trunk/extensions/Translate/tag/SpecialPageTranslation.php |
— | — | @@ -393,6 +393,7 @@ |
394 | 394 | // Store changed sections in the database for easy access. |
395 | 395 | // Used when determinen the up-to-datedness for section translations. |
396 | 396 | $page->addMarkedTag( $newrevision, $changed ); |
| 397 | + $this->addFuzzyTags( $page, $changed ); |
397 | 398 | |
398 | 399 | $this->setupRenderJobs( $page ); |
399 | 400 | |
— | — | @@ -403,6 +404,37 @@ |
404 | 405 | return false; |
405 | 406 | } |
406 | 407 | |
| 408 | + public function addFuzzyTags( $page, $changed ) { |
| 409 | + $titles = array(); |
| 410 | + $prefix = $page->getTitle->getPrefixedText(); |
| 411 | + $db = wfGetDB( DB_MASTER ); |
| 412 | + foreach ( $changed as $c ) { |
| 413 | + $title = Title::makeTitleSafe( NS_TRANSLATIONS, "$prefix/$c" ); |
| 414 | + if ( $title ) { |
| 415 | + $titles[] = 'page_title like \'' . $db->escapeLike( $title->getPrefixedDBkey() ) . '/%\''; |
| 416 | + } |
| 417 | + } |
| 418 | + |
| 419 | + $titleCond = $db->makeList( $titles, LIST_OR ); |
| 420 | + |
| 421 | + $id = $db->selectField( 'revtag_type', 'rtt_id', array( 'rtt_name' => 'fuzzy' ), __METHOD__ ); |
| 422 | + |
| 423 | + $fields = array( 'page_id', 'page_latest' ); |
| 424 | + $conds = array( 'page_namespace' => NS_TRANSLATIONS, $titleCond ); |
| 425 | + $res = $db->select( 'page', $fields, $conds, __METHOD__ ); |
| 426 | + |
| 427 | + $inserts = array(); |
| 428 | + |
| 429 | + foreach( $res as $r ) { |
| 430 | + $inserts[] = array( |
| 431 | + 'rt_page' => $r->page_id, |
| 432 | + 'rt_type' => $id, |
| 433 | + 'rt_revision' => $r->page_latest, |
| 434 | + ); |
| 435 | + } |
| 436 | + $db->replace( 'revtag', array( 'rt_type_page_revision' ), $inserts, __METHOD__ ); |
| 437 | + } |
| 438 | + |
407 | 439 | public function setupRenderJobs( TranslatablePage $page ) { |
408 | 440 | $titles = $page->getTranslationPages(); |
409 | 441 | $jobs = array(); |
Index: trunk/extensions/Translate/tag/TPParse.php |
— | — | @@ -111,6 +111,8 @@ |
112 | 112 | // For finding the messages |
113 | 113 | $prefix = $this->title->getPrefixedDBKey() . '/'; |
114 | 114 | |
| 115 | + $collection->loadTranslations(); |
| 116 | + |
115 | 117 | foreach ( $this->sections as $ph => $s ) { |
116 | 118 | if ( isset($collection[$prefix.$s->id]) ) { |
117 | 119 | $msg = $collection[$prefix.$s->id]; |
Index: trunk/extensions/Translate/tag/TranslatablePage.php |
— | — | @@ -301,7 +301,6 @@ |
302 | 302 | foreach ( $titles as $t ) { |
303 | 303 | list( , $code ) = TranslateUtils::figureMessage( $t->getText() ); |
304 | 304 | $collection = $group->initCollection( $code ); |
305 | | - $group->fillCollection( $collection ); |
306 | 305 | |
307 | 306 | $percent = $this->getPercentageInternal( $collection, $markedRevs ); |
308 | 307 | // To avoid storing 40 decimals of inaccuracy, truncate to two decimals |
— | — | @@ -320,16 +319,17 @@ |
321 | 320 | $count = count($collection); |
322 | 321 | if ( $count === 0 ) return 0; |
323 | 322 | |
| 323 | + // We want to get fuzzy though |
| 324 | + $collection->filter( 'hastranslation', false ); |
| 325 | + $collection->initMessages(); |
| 326 | + |
324 | 327 | $total = 0; |
325 | 328 | |
326 | 329 | foreach ( $collection as $key => $message ) { |
327 | | - |
328 | | - if ( $message->translation() === null ) continue; // No score |
329 | | - |
330 | 330 | $score = 1; |
331 | 331 | |
332 | 332 | // Fuzzy halves score |
333 | | - if ( $message->fuzzy() ) $score *= 0.5; |
| 333 | + if ( $message->hasTag('fuzzy') ) $score *= 0.5; |
334 | 334 | |
335 | 335 | // Reduce 20% for every newer revision than what is translated against |
336 | 336 | $rev = $this->getTransrev( $key .'/' . $collection->code ); |
Index: trunk/extensions/Translate/TranslateEditAddons.php |
— | — | @@ -18,9 +18,8 @@ |
19 | 19 | |
20 | 20 | if ( !in_array( $ns, $wgTranslateMessageNamespaces) ) return true; |
21 | 21 | |
22 | | - list( $key, $code ) = self::figureMessage( $wgTitle ); |
23 | 22 | |
24 | | - $group = self::getMessageGroup( $ns, $key ); |
| 23 | + list( $key, $code, $group) = self::getKeyCodeGroup( $wgTitle ); |
25 | 24 | if ( $group === null ) return true; |
26 | 25 | |
27 | 26 | $defs = $group->getDefinitions(); |
— | — | @@ -213,7 +212,7 @@ |
214 | 213 | /** |
215 | 214 | * @return Array of the message and the language |
216 | 215 | */ |
217 | | - private static function figureMessage( $title ) { |
| 216 | + private static function figureMessage( Title $title ) { |
218 | 217 | $text = $title->getDBkey(); |
219 | 218 | $pos = strrpos( $text, '/' ); |
220 | 219 | $code = substr( $text, $pos + 1 ); |
— | — | @@ -221,6 +220,12 @@ |
222 | 221 | return array( $key, $code ); |
223 | 222 | } |
224 | 223 | |
| 224 | + public static function getKeyCodeGroup( Title $title ) { |
| 225 | + list( $key, $code ) = self::figureMessage( $title ); |
| 226 | + $group = self::getMessageGroup( $title->getNamespace(), $key ); |
| 227 | + return array( $key, $code, $group ); |
| 228 | + } |
| 229 | + |
225 | 230 | /** |
226 | 231 | * Tries to determine from which group this message belongs. It tries to get |
227 | 232 | * group id from loadgroup GET-paramater, but fallbacks to messageIndex file |
— | — | @@ -249,9 +254,7 @@ |
250 | 255 | wfLoadExtensionMessages( 'Translate' ); |
251 | 256 | global $wgTranslateDocumentationLanguageCode, $wgOut, $wgTranslateMessageNamespaces; |
252 | 257 | |
253 | | - list( $key, $code ) = self::figureMessage( $object->mTitle ); |
254 | | - |
255 | | - $group = self::getMessageGroup( $object->mTitle->getNamespace(), $key ); |
| 258 | + list( $key, $code, $group ) = self::getKeyCodeGroup( $object->mTitle ); |
256 | 259 | if ( $group === null ) return; |
257 | 260 | |
258 | 261 | list( $nsMain, /* $nsTalk */ ) = $group->namespaces; |
— | — | @@ -264,11 +267,7 @@ |
265 | 268 | $inOtherLanguages = array(); |
266 | 269 | $namespace = $object->mTitle->getNsText(); |
267 | 270 | foreach ( self::getFallbacks( $code ) as $fbcode ) { |
268 | | - $fb = $group->getMessage( $key, $fbcode ); |
269 | | - /* For fallback, even uncommitted translation may be useful */ |
270 | | - if ( $fb === null ) { |
271 | | - $fb = TranslateUtils::getMessageContent( $key, $fbcode ); |
272 | | - } |
| 271 | + $fb = TranslateUtils::getMessageContent( $key, $fbcode, $nsMain ); |
273 | 272 | if ( $fb !== null ) { |
274 | 273 | /* add a link for editing the fallback messages */ |
275 | 274 | $inOtherLanguages[] = self::dobox( $fb, $fbcode, false, $namespace . ':' . $key . '/' . $fbcode ); |
— | — | @@ -376,9 +375,9 @@ |
377 | 376 | // Some syntactic checks |
378 | 377 | $translation = ( $editField !== null ) ? $editField : $xx; |
379 | 378 | if ( $translation !== null && $code !== $wgTranslateDocumentationLanguageCode) { |
380 | | - $message = new TMessage( $key, $en ); |
| 379 | + $message = new FatMessage( $key, $en ); |
381 | 380 | // Take the contents from edit field as a translation |
382 | | - $message->database = $translation; |
| 381 | + $message->setTranslation( $translation ); |
383 | 382 | $checker = MessageChecks::getInstance(); |
384 | 383 | if ( $checker->hasChecks( $group->getType() ) ) { |
385 | 384 | $checks = $checker->doChecks( $message, $group->getType(), $code ); |
— | — | @@ -420,4 +419,63 @@ |
421 | 420 | ); |
422 | 421 | return true; |
423 | 422 | } |
| 423 | + |
| 424 | + public static function onSave( $article, $user, $text, $summary, |
| 425 | + $minor, $_, $_, $flags, $revision ) { |
| 426 | + |
| 427 | + global $wgTranslateMessageNamespaces; |
| 428 | + |
| 429 | + $title = $article->getTitle(); |
| 430 | + |
| 431 | + $ns = $title->getNamespace(); |
| 432 | + if ( !in_array( $ns, $wgTranslateMessageNamespaces) ) return true; |
| 433 | + |
| 434 | + list( $key, $code, $group ) = self::getKeyCodeGroup( $title ); |
| 435 | + $cache = new ArrayMemoryCache( 'groupstats' ); |
| 436 | + $cache->clear( $group->getId(), $code ); |
| 437 | + |
| 438 | + $fuzzy = false; |
| 439 | + |
| 440 | + // Check for explicit tag |
| 441 | + if ( strpos( $text, TRANSLATE_FUZZY ) !== false ) $fuzzy = true; |
| 442 | + |
| 443 | + // Check for problems |
| 444 | + global $wgTranslateDocumentationLanguageCode; |
| 445 | + if ( !$fuzzy && $code !== $wgTranslateDocumentationLanguageCode ) { |
| 446 | + $message = new FatMessage( $key, $en ); |
| 447 | + // Take the contents from edit field as a translation |
| 448 | + $message->setTranslation( $translation ); |
| 449 | + $checker = MessageChecks::getInstance(); |
| 450 | + if ( $checker->hasChecks( $group->getType() ) ) { |
| 451 | + $checks = $checker->doChecks( $message, $group->getType(), $code ); |
| 452 | + if ( count( $checks ) ) $fuzzy = true; |
| 453 | + } |
| 454 | + } |
| 455 | + |
| 456 | + if ( $fuzzy === false ) return true; |
| 457 | + |
| 458 | + // Update it |
| 459 | + if ( $revision === null ) { |
| 460 | + $rev = $article->getTitle()->getLatestRevId(); |
| 461 | + } else { |
| 462 | + $rev = $revision->getID(); |
| 463 | + } |
| 464 | + |
| 465 | + // Add the ready tag |
| 466 | + $dbw = wfGetDB( DB_MASTER ); |
| 467 | + |
| 468 | + $id = $dbw->selectField( 'revtag_type', 'rtt_id', array( 'rtt_name' => 'fuzzy' ), __METHOD__ ); |
| 469 | + |
| 470 | + $conds = array( |
| 471 | + 'rt_page' => $article->getTitle()->getArticleId(), |
| 472 | + 'rt_type' => $id, |
| 473 | + 'rt_revision' => $rev |
| 474 | + ); |
| 475 | + $dbw->delete( 'revtag', $conds, __METHOD__ ); |
| 476 | + $dbw->insert( 'revtag', $conds, __METHOD__ ); |
| 477 | + |
| 478 | + return true; |
| 479 | + } |
| 480 | + |
424 | 481 | } |
| 482 | + |
Index: trunk/extensions/Translate/Translate.php |
— | — | @@ -11,7 +11,7 @@ |
12 | 12 | * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
13 | 13 | */ |
14 | 14 | |
15 | | -define( 'TRANSLATE_VERSION', '11:2009-05-09' ); |
| 15 | +define( 'TRANSLATE_VERSION', '12bb:2009-05-28' ); |
16 | 16 | |
17 | 17 | $wgExtensionCredits['specialpage'][] = array( |
18 | 18 | 'path' => __FILE__, |
— | — | @@ -164,12 +164,10 @@ |
165 | 165 | 'view' => 'ViewMessagesTask', |
166 | 166 | 'untranslated' => 'ViewUntranslatedTask', |
167 | 167 | 'optional' => 'ViewOptionalTask', |
168 | | - 'untranslatedoptional' => 'ViewUntranslatedOptionalTask', |
169 | | - 'problematic' => 'ViewProblematicTask', |
| 168 | +// 'untranslatedoptional' => 'ViewUntranslatedOptionalTask', |
170 | 169 | 'review' => 'ReviewMessagesTask', |
171 | 170 | 'reviewall' => 'ReviewAllMessagesTask', |
172 | 171 | 'export-as-po' => 'ExportasPoMessagesTask', |
173 | | -// 'export' => 'ExportMessagesTask', |
174 | 172 | 'export-to-file' => 'ExportToFileMessagesTask', |
175 | 173 | // 'export-to-xliff' => 'ExportToXliffMessagesTask', |
176 | 174 | ); |
— | — | @@ -198,9 +196,8 @@ |
199 | 197 | } |
200 | 198 | |
201 | 199 | // Fuzzy tags for speed |
202 | | - $wgHooks['ArticleSaveComplete'][] = 'efTranslateAddFuzzy'; |
| 200 | + $wgHooks['ArticleSaveComplete'][] = 'TranslateEditAddons::onSave'; |
203 | 201 | |
204 | | - |
205 | 202 | global $wgEnablePageTranslation; |
206 | 203 | if ( $wgEnablePageTranslation ) { |
207 | 204 | |
— | — | @@ -265,7 +262,6 @@ |
266 | 263 | $memcKey = wfMemcKey( 'pt' ); |
267 | 264 | $ok = $wgMemc->get( $memcKey ); |
268 | 265 | |
269 | | - wfLoadExtensionMessages( 'PageTranslation' ); |
270 | 266 | if ( $ok === $version ) { |
271 | 267 | return true; |
272 | 268 | } |
— | — | @@ -277,7 +273,7 @@ |
278 | 274 | |
279 | 275 | $dbw = wfGetDB( DB_MASTER ); |
280 | 276 | if ( !$dbw->tableExists('revtag_type') ) { |
281 | | - $wgHooks['SiteNoticeAfter'][] = array('efTranslateCheckWarn', wfMsg( 'tpt-install' ) ); |
| 277 | + $wgHooks['SiteNoticeAfter'][] = array('efTranslateCheckWarn', 'tpt-install' ); |
282 | 278 | return false; |
283 | 279 | } |
284 | 280 | |
— | — | @@ -295,7 +291,8 @@ |
296 | 292 | |
297 | 293 | function efTranslateCheckWarn( $msg, &$sitenotice ) { |
298 | 294 | global $wgOut; |
299 | | - $sitenotice = $msg; |
| 295 | + wfLoadExtensionMessages( 'PageTranslation' ); |
| 296 | + $sitenotice = wfMsg($msg); |
300 | 297 | $wgOut->enableClientCache( false ); |
301 | 298 | return true; |
302 | 299 | } |
— | — | @@ -305,42 +302,3 @@ |
306 | 303 | $parser->setHook( 'languages', array( 'PageTranslationHooks', 'languages' ) ); |
307 | 304 | return true; |
308 | 305 | } |
309 | | - |
310 | | - |
311 | | -if ( !defined('TRANSLATE_CLI') ) { |
312 | | - function STDOUT() {} |
313 | | - function STDERR() {} |
314 | | -} |
315 | | - |
316 | | -function efTranslateAddFuzzy( $article, $user, $text, $summary, |
317 | | - $minor, $_, $_, $flags, $revision ) { |
318 | | - |
319 | | - global $wgTranslateMessageNamespaces; |
320 | | - |
321 | | - $ns = $article->getTitle()->getNamespace(); |
322 | | - if ( !in_array( $ns, $wgTranslateMessageNamespaces) ) return true; |
323 | | - |
324 | | - // No fuzzy - no tag |
325 | | - if ( strpos( $text, TRANSLATE_FUZZY ) === false ) return true; |
326 | | - |
327 | | - if ( $revision === null ) { |
328 | | - $rev = $article->getTitle()->getLatestRevId(); |
329 | | - } else { |
330 | | - $rev = $revision->getID(); |
331 | | - } |
332 | | - |
333 | | - // Add the ready tag |
334 | | - $dbw = wfGetDB( DB_MASTER ); |
335 | | - |
336 | | - $id = $dbw->selectField( 'revtag_type', 'rtt_id', array( 'rtt_name' => 'fuzzy' ), __METHOD__ ); |
337 | | - |
338 | | - $conds = array( |
339 | | - 'rt_page' => $article->getTitle()->getArticleId(), |
340 | | - 'rt_type' => $id, |
341 | | - 'rt_revision' => $rev |
342 | | - ); |
343 | | - $dbw->delete( 'revtag', $conds, __METHOD__ ); |
344 | | - $dbw->insert( 'revtag', $conds, __METHOD__ ); |
345 | | - |
346 | | - return true; |
347 | | -} |
\ No newline at end of file |
Index: trunk/extensions/Translate/SpecialLanguageStats.php |
— | — | @@ -192,29 +192,38 @@ |
193 | 193 | |
194 | 194 | $out = ''; |
195 | 195 | |
| 196 | + $cache = new ArrayMemoryCache( 'groupstats' ); |
| 197 | + |
196 | 198 | # Fetch groups stats have to be displayed for |
197 | 199 | $groups = $this->getGroups(); |
198 | 200 | |
199 | 201 | # Get statistics for the message groups |
200 | | - foreach ( $groups as $g ) { |
| 202 | + foreach ( $groups as $groupName => $g ) { |
201 | 203 | |
202 | | - // Initialise messages |
203 | | - $collection = $g->initCollection( $code ); |
204 | | - $collection->filter( 'optional' ); |
205 | | - // Store the count of real messages for later calculation. |
206 | | - $total = count( $collection ); |
| 204 | + $incache = $cache->get( $groupName, $code ); |
| 205 | + if ( $incache !== false ) { |
| 206 | + list( $fuzzy, $translated, $total ) = $incache; |
| 207 | + } else { |
207 | 208 | |
208 | | - // Fill translations in for counting |
209 | | - $g->fillCollection( $collection ); |
| 209 | + // Initialise messages |
| 210 | + $collection = $g->initCollection( $code ); |
| 211 | + $collection->filter( 'ignored' ); |
| 212 | + $collection->filter( 'optional' ); |
| 213 | + // Store the count of real messages for later calculation. |
| 214 | + $total = count( $collection ); |
210 | 215 | |
211 | | - // Count fuzzy first |
212 | | - $collection->filter( 'fuzzy' ); |
213 | | - $fuzzy = $total - count( $collection ); |
| 216 | + // Count fuzzy first |
| 217 | + $collection->filter( 'fuzzy' ); |
| 218 | + $fuzzy = $total - count( $collection ); |
214 | 219 | |
215 | | - // Count the completion percent |
216 | | - $collection->filter( 'translated', false ); |
217 | | - $translated = count( $collection ); |
| 220 | + // Count the completion percent |
| 221 | + $collection->filter( 'hastranslation', false ); |
| 222 | + $translated = count( $collection ); |
218 | 223 | |
| 224 | + $cache->set( $groupName, $code, array( $fuzzy, $translated, $total ) ); |
| 225 | + |
| 226 | + } |
| 227 | + |
219 | 228 | // FIXME: avoid division by 0. Should not happen, but core-mostused has this on Windows at the moment |
220 | 229 | if( !$total ) { |
221 | 230 | continue; |
Index: trunk/extensions/Translate/_autoload.php |
— | — | @@ -22,8 +22,11 @@ |
23 | 23 | $wgAutoloadClasses['WikiPageMessageGroup'] = $dir . 'MessageGroups.php'; |
24 | 24 | $wgAutoloadClasses['AliasMessageGroup'] = $dir . 'MessageGroups.php'; |
25 | 25 | |
26 | | -$wgAutoloadClasses['MessageCollection'] = $dir . 'Message.php'; |
| 26 | +$wgAutoloadClasses['MessageCollection'] = $dir . 'MessageCollection.php'; |
| 27 | +$wgAutoloadClasses['MessageDefinitions'] = $dir . 'MessageCollection.php'; |
27 | 28 | $wgAutoloadClasses['TMessage'] = $dir . 'Message.php'; |
| 29 | +$wgAutoloadClasses['ThinMessage'] = $dir . 'Message.php'; |
| 30 | +$wgAutoloadClasses['FatMessage'] = $dir . 'Message.php'; |
28 | 31 | |
29 | 32 | $wgAutoloadClasses['TranslateEditAddons'] = $dir . 'TranslateEditAddons.php'; |
30 | 33 | $wgAutoloadClasses['languages'] = $IP . '/maintenance/language/languages.inc'; |
— | — | @@ -60,6 +63,8 @@ |
61 | 64 | $wgAutoloadClasses['StringMatcher'] = $dir . 'utils/StringMatcher.php'; |
62 | 65 | $wgAutoloadClasses['FCFontFinder'] = $dir . 'utils/Font.php'; |
63 | 66 | |
| 67 | +$wgAutoloadClasses['ArrayMemoryCache'] = $dir . 'utils/MemoryCache.php'; |
| 68 | + |
64 | 69 | $wgAutoloadClasses['StringMangler'] = $dir . 'utils/StringMangler.php'; |
65 | 70 | $wgAutoloadClasses['SmItem'] = $dir . 'utils/StringMangler.php'; |
66 | 71 | $wgAutoloadClasses['SmRewriter'] = $dir . 'utils/StringMangler.php'; |
Index: trunk/extensions/Translate/utils/MemoryCache.php |
— | — | @@ -0,0 +1,54 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class ArrayMemoryCache { |
| 5 | + protected $table; |
| 6 | + protected $key; |
| 7 | + protected $memc; |
| 8 | + protected $cache; |
| 9 | + |
| 10 | + public function __construct( $table ) { |
| 11 | + $this->table = $table; |
| 12 | + $this->key = wfMemcKey( $this->table ); |
| 13 | + global $wgMemc; |
| 14 | + $this->memc = $wgMemc; |
| 15 | + } |
| 16 | + |
| 17 | + public function __destruct() { |
| 18 | + $this->save(); |
| 19 | + } |
| 20 | + |
| 21 | + public function get( $group, $code ) { |
| 22 | + $this->load(); |
| 23 | + if ( !isset($this->cache[$group][$code]) ) return false; |
| 24 | + return explode( ',', $this->cache[$group][$code] ); |
| 25 | + } |
| 26 | + |
| 27 | + public function set( $group, $code, $value ) { |
| 28 | + $this->load(); |
| 29 | + if ( !isset($this->cache[$group]) ) $this->cache[$group] = array(); |
| 30 | + $this->cache[$group][$code] = implode(',', $value); |
| 31 | + } |
| 32 | + |
| 33 | + public function clear( $group, $code ) { |
| 34 | + $this->load(); |
| 35 | + unset($this->cache[$group][$code]); |
| 36 | + if ( !count($this->cache[$group]) ) unset($this->cache[$group]); |
| 37 | + } |
| 38 | + |
| 39 | + public function commit() { |
| 40 | + $this->load(); |
| 41 | + $this->save(); |
| 42 | + } |
| 43 | + |
| 44 | + |
| 45 | + protected function load() { |
| 46 | + if ( $this->cache === null ) { |
| 47 | + $this->cache = $this->memc->get( $this->key ); |
| 48 | + if ( !is_array($this->cache) ) $this->cache = array(); |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + protected function save() { |
| 53 | + $this->memc->set( $this->key, $this->cache ); |
| 54 | + } |
| 55 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/Translate/utils/MemoryCache.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 56 | + native |
Index: trunk/extensions/Translate/utils/MessageTable.php |
— | — | @@ -83,21 +83,23 @@ |
84 | 84 | global $wgUser; |
85 | 85 | $sk = $wgUser->getSkin(); |
86 | 86 | wfLoadExtensionMessages( 'Translate' ); |
| 87 | + $optional = wfMsgHtml( 'translate-optional' ); |
87 | 88 | |
88 | | - $uimsg = array(); |
89 | | - foreach ( array( 'optional' ) as $msg ) { |
90 | | - $uimsg[$msg] = wfMsgHtml( 'translate-'.$msg ); |
| 89 | + $batch = new LinkBatch(); |
| 90 | + $ns = $this->group->namespaces[0]; |
| 91 | + foreach ( $this->collection->keys() as $key ) { |
| 92 | + $batch->add( $ns, $key ); |
91 | 93 | } |
| 94 | + $batch->execute(); |
92 | 95 | |
93 | 96 | $output = ''; |
94 | | - |
| 97 | + $this->collection->initMessages(); // Just to be sure |
95 | 98 | foreach ( $this->collection as $key => $m ) { |
96 | | - |
97 | 99 | $tools = array(); |
98 | 100 | $title = $this->keyToTitle( $key ); |
99 | 101 | |
100 | | - $original = $m->definition; |
101 | | - $message = $m->translation ? $m->translation : $original; |
| 102 | + $original = $m->definition(); |
| 103 | + $message = $m->translation() ? $m->translation() : $original; |
102 | 104 | |
103 | 105 | global $wgLang; |
104 | 106 | $niceTitle = htmlspecialchars( $wgLang->truncate( $key, - 30 ) ); |
— | — | @@ -114,11 +116,11 @@ |
115 | 117 | $anchor = Xml::element( 'a', array( 'name' => $anchor, 'href' => "#$anchor" ), "↓" ); |
116 | 118 | |
117 | 119 | $extra = ''; |
118 | | - if ( $m->optional ) $extra = '<br />' . $uimsg['optional']; |
| 120 | + if ( $m->hasTag( 'optional' ) ) $extra = '<br />' . $optional; |
119 | 121 | |
120 | 122 | $leftColumn = $anchor . $tools['edit'] . $extra; |
121 | 123 | |
122 | | - if ( $this->reviewMode ) { |
| 124 | + if ( $this->reviewMode && $original !== $message ) { |
123 | 125 | $output .= Xml::tags( 'tr', array( 'class' => 'orig' ), |
124 | 126 | Xml::tags( 'td', array( 'rowspan' => '2' ), $leftColumn ) . |
125 | 127 | Xml::tags( 'td', null, TranslateUtils::convertWhiteSpaceToHTML( $original ) ) |
Index: trunk/extensions/Translate/ffs/Java.php |
— | — | @@ -119,9 +119,9 @@ |
120 | 120 | */ |
121 | 121 | protected function exportMessages( $handle, MessageCollection $collection ) { |
122 | 122 | $mangler = $this->group->getMangler(); |
123 | | - foreach ( $collection->keys() as $item ) { |
124 | | - $key = $mangler->unmangle( $item ); |
125 | | - $value = str_replace( TRANSLATE_FUZZY, '', $collection[$item]->translation ); |
| 123 | + foreach ( $collection as $key => $item ) { |
| 124 | + $key = $mangler->unmangle( $key ); |
| 125 | + $value = str_replace( TRANSLATE_FUZZY, '', $item->translation() ); |
126 | 126 | |
127 | 127 | # Make sure we don't slip newlines trough... it would be fatal |
128 | 128 | $value = str_replace( "\n", '\\n', $value ); |
Index: trunk/extensions/Translate/ffs/OpenLayers.php |
— | — | @@ -118,7 +118,9 @@ |
119 | 119 | |
120 | 120 | // Get and write messages. |
121 | 121 | foreach( $collection as $message ) { |
122 | | - $value = str_replace( '"', '\"', $message->database() ); |
| 122 | + $key = Xml::escapeJsString( $message->key() ); |
| 123 | + $value = Xml::escapeJsString( $message->translation() ); |
| 124 | + |
123 | 125 | $line = " '{$message->key()}': \"{$value}\",\n\n"; |
124 | 126 | fwrite( $target, $line ); |
125 | 127 | } |
Index: trunk/extensions/Translate/ffs/Wiki.php |
— | — | @@ -142,7 +142,7 @@ |
143 | 143 | foreach ( $messages as $key => $m ) { |
144 | 144 | $key = $mangler->unMangle( $key ); |
145 | 145 | # Remove fuzzy markings before export |
146 | | - $translation = str_replace( TRANSLATE_FUZZY, '', $m->translation ); |
| 146 | + $translation = str_replace( TRANSLATE_FUZZY, '', $m->translation() ); |
147 | 147 | $new[$key] = $translation; |
148 | 148 | } |
149 | 149 | |
Index: trunk/extensions/Translate/ffs/Gettext.php |
— | — | @@ -248,12 +248,12 @@ |
249 | 249 | foreach ( $messages as $key => $m ) { |
250 | 250 | $flags = array(); |
251 | 251 | |
252 | | - $translation = $m->translation; |
| 252 | + $translation = $m->translation(); |
253 | 253 | # CASE2: no translation |
254 | 254 | if ( $translation === null ) $translation = ''; |
255 | 255 | |
256 | 256 | # CASE3: optional messages; accept only if different |
257 | | - if ( $m->optional ) $flags[] = 'x-optional'; |
| 257 | + if ( $m->hasTag( 'optional') ) $flags[] = 'x-optional'; |
258 | 258 | |
259 | 259 | # Remove fuzzy markings before export |
260 | 260 | $flags = array(); |
— | — | @@ -282,7 +282,7 @@ |
283 | 283 | if ( isset( $this->data[$key]['ctxt'] ) ) { |
284 | 284 | $ckey = $this->data[$key]['ctxt']; |
285 | 285 | } |
286 | | - fwrite( $handle, $this->formatmsg( $m->definition, $translation, $ckey ) ); |
| 286 | + fwrite( $handle, $this->formatmsg( $m->definition(), $translation, $ckey ) ); |
287 | 287 | |
288 | 288 | } |
289 | 289 | |
Index: trunk/extensions/Translate/ffs/Xliff.php |
— | — | @@ -59,11 +59,11 @@ |
60 | 60 | protected function messages( XMLWriter $w, $handle, MessageCollection $collection ) { |
61 | 61 | $w->startElement( 'body' ); |
62 | 62 | |
63 | | - foreach ( $collection->keys() as $key ) { |
| 63 | + foreach ( $collection as $key => $m) { |
64 | 64 | $w->startElement( 'trans-unit' ); |
65 | 65 | $w->writeAttribute( 'id', $key ); |
66 | | - $w->writeElement( 'source', $collection[$key]->definition ); |
67 | | - $translation = $collection[$key]->translation; |
| 66 | + $w->writeElement( 'source', $m->definition() ); |
| 67 | + $translation = $m->translatiom(); |
68 | 68 | if ( $translation !== null ) { |
69 | 69 | $w->writeElement( 'target', $translation ); |
70 | 70 | } |
Index: trunk/extensions/Translate/ffs/Simple.php |
— | — | @@ -171,8 +171,8 @@ |
172 | 172 | |
173 | 173 | protected function getMessagesForExport( MessageGroup $group, $code ) { |
174 | 174 | $collection = $this->group->initCollection( $code ); |
175 | | - $this->group->fillCollection( $collection ); |
176 | | - $collection->filter( 'translation', null ); |
| 175 | + $collection->filter( 'hastranslation', false ); |
| 176 | + $collection->loadTranslations(); |
177 | 177 | $this->addAuthors( $collection->getAuthors(), $code ); |
178 | 178 | return $collection; |
179 | 179 | } |
— | — | @@ -245,9 +245,9 @@ |
246 | 246 | |
247 | 247 | protected function exportMessages( $handle, MessageCollection $collection ) { |
248 | 248 | $mangler = $this->group->getMangler(); |
249 | | - foreach ( $collection->keys() as $item ) { |
250 | | - $key = $mangler->unMangle( $item ); |
251 | | - $value = str_replace( TRANSLATE_FUZZY, '', $collection[$item]->translation ); |
| 249 | + foreach ( $collection as $item ) { |
| 250 | + $key = $mangler->unMangle( $item->key() ); |
| 251 | + $value = str_replace( TRANSLATE_FUZZY, '', $item->translation() ); |
252 | 252 | fwrite( $handle, "$key\000$value\000\n" ); |
253 | 253 | } |
254 | 254 | } |
Index: trunk/extensions/Translate/ffs/PhpVariables.php |
— | — | @@ -143,12 +143,12 @@ |
144 | 144 | */ |
145 | 145 | protected function exportMessages( $handle, MessageCollection $collection ) { |
146 | 146 | $mangler = $this->group->getMangler(); |
147 | | - foreach ( $collection->keys() as $item ) { |
| 147 | + foreach ( $collection as $item ) { |
148 | 148 | |
149 | | - $key = $mangler->unmangle( $item ); |
| 149 | + $key = $mangler->unmangle( $item->key() ); |
150 | 150 | $key = stripcslashes( $key ); |
151 | 151 | |
152 | | - $value = $collection[$item]->translation; |
| 152 | + $value = $item->translation(); |
153 | 153 | $value = str_replace( TRANSLATE_FUZZY, '', $value ); |
154 | 154 | $value = addcslashes( $value, "'" ); |
155 | 155 | |
Index: trunk/extensions/Translate/MessageCollection.php |
— | — | @@ -0,0 +1,423 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 4 | +/** |
| 5 | + * An extension to ease the translation of Mediawiki |
| 6 | + * |
| 7 | + * @addtogroup Extensions |
| 8 | + * |
| 9 | + * @author Niklas Laxström |
| 10 | + * @copyright Copyright © 2007-2009, Niklas Laxström |
| 11 | + * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later |
| 12 | + */ |
| 13 | + |
| 14 | +class MessageCollection implements ArrayAccess, Iterator, Countable { |
| 15 | + /** |
| 16 | + * It is handy to store the language code here. |
| 17 | + */ |
| 18 | + public $code = null; |
| 19 | + |
| 20 | + // External stuff |
| 21 | + private $definitions = null; // MessageDefinitions |
| 22 | + private $infile = array(); // message key => translation |
| 23 | + |
| 24 | + // Keys and messages |
| 25 | + private $keys = null; // message key => database key |
| 26 | + private $messages = null; // message key => ThinMessage |
| 27 | + |
| 28 | + // Database resources |
| 29 | + private $dbInfo = null; // existence, fuzzy |
| 30 | + private $dbData = null; // all translations |
| 31 | + |
| 32 | + // Tags, copied to thin messages |
| 33 | + private $tags = array(); // tagtype => keys |
| 34 | + |
| 35 | + // Constructors etc. |
| 36 | + // |
| 37 | + public function __construct( $code ) { |
| 38 | + $this->code = $code; |
| 39 | + } |
| 40 | + |
| 41 | + public static function newFromDefinitions( MessageDefinitions $definitions, $code ) { |
| 42 | + $collection = new self( $code ); |
| 43 | + $collection->definitions = $definitions; |
| 44 | + $collection->resetForNewLanguage( $code ); |
| 45 | + return $collection; |
| 46 | + } |
| 47 | + |
| 48 | + // Data setters |
| 49 | + // |
| 50 | + public function setInfile( array $messages ) { |
| 51 | + $this->infile = $messages; |
| 52 | + } |
| 53 | + |
| 54 | + public function setTags( $type, array $keys ) { |
| 55 | + $this->tags[$type] = $keys; |
| 56 | + } |
| 57 | + |
| 58 | + // Getters |
| 59 | + public function keys() { |
| 60 | + return $this->keys; |
| 61 | + } |
| 62 | + |
| 63 | + public function getTags( $type ) { |
| 64 | + return isset($this->tags[$type]) ? $this->tags[$type] : null; |
| 65 | + } |
| 66 | + |
| 67 | + public function getAuthors() { |
| 68 | + global $wgTranslateFuzzyBotName; |
| 69 | + |
| 70 | + $this->loadTranslations(); |
| 71 | + |
| 72 | + $authors = array(); |
| 73 | + foreach ( $this->messages as $m ) { |
| 74 | + // Check if there is authors |
| 75 | + $author = $m->author(); |
| 76 | + if ( $author === null ) continue; |
| 77 | + if ( !isset( $authors[$author] ) ) { |
| 78 | + $authors[$author] = 1; |
| 79 | + } else { |
| 80 | + $authors[$author]++; |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + arsort( $authors, SORT_NUMERIC ); |
| 85 | + foreach ( $authors as $author => $edits ) { |
| 86 | + if ( $author !== $wgTranslateFuzzyBotName ) { |
| 87 | + $filteredAuthors[] = $author; |
| 88 | + } |
| 89 | + } |
| 90 | + return isset( $filteredAuthors ) ? $filteredAuthors : array(); |
| 91 | + } |
| 92 | + |
| 93 | + // Data modifiers |
| 94 | + |
| 95 | + public function loadTranslations() { |
| 96 | + $this->loadData( $this->keys ); |
| 97 | + $this->initMessages(); |
| 98 | + } |
| 99 | + |
| 100 | + /** |
| 101 | + * Filters messages based on some condition. Some filters cause data to be |
| 102 | + * loaded from the database. PAGEINFO: existence and fuzzy tags. |
| 103 | + * TRANSLATIONS: translations for every message. It is recommended to first |
| 104 | + * filter with messages that do not need those. It is recommended to add |
| 105 | + * translations from file with addInfile, and it is needed for chagned |
| 106 | + * filter to work. |
| 107 | + * |
| 108 | + * @param $type |
| 109 | + * fuzzy: messages with fuzzy tag (PAGEINFO) |
| 110 | + * optional: messages marked for optional. |
| 111 | + * ignored: messages which are not for translation. |
| 112 | + * hastranslation: messages which have translation (be if fuzzy or not) (PAGEINFO, *INFILE). |
| 113 | + * translated: messages which have translation which is not fuzzy (PAGEINFO, *INFILE). |
| 114 | + * changed: translation in database differs from infile. (INFILE, TRANSLATIONS) |
| 115 | + * @param $condition True or false. |
| 116 | + */ |
| 117 | + public function filter( $type, $condition = true ) { |
| 118 | + switch( $type ) { |
| 119 | + case 'fuzzy': |
| 120 | + case 'optional': |
| 121 | + case 'ignored': |
| 122 | + case 'hastranslation': |
| 123 | + case 'changed': |
| 124 | + case 'translated': |
| 125 | + $this->applyFilter( $type, $condition ); |
| 126 | + break; |
| 127 | + default: |
| 128 | + throw new MWException( "Unknown filter $type" ); |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | + /** |
| 133 | + * Some statistics scripts for example loop the same collection over every |
| 134 | + * language. This is a shortcut which keeps tags and definitions. |
| 135 | + */ |
| 136 | + public function resetForNewLanguage( $code ) { |
| 137 | + $this->code = $code; |
| 138 | + |
| 139 | + $this->keys = $this->fixKeys( array_keys($this->definitions->messages) ); |
| 140 | + $this->dbInfo = null; |
| 141 | + $this->dbData = null; |
| 142 | + $this->messages = null; |
| 143 | + $this->infile = array(); |
| 144 | + unset($this->tags['fuzzy']); |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * For paging messages. One can count messages before and after slice. |
| 149 | + */ |
| 150 | + public function slice( $offset, $limit ) { |
| 151 | + $this->keys = array_slice( $this->keys, $offset, $limit, true ); |
| 152 | + } |
| 153 | + |
| 154 | + // Protected functions |
| 155 | + // |
| 156 | + protected function applyFilter( $filter, $condition ) { |
| 157 | + $keys = $this->keys; |
| 158 | + if ( $filter === 'fuzzy' ) { |
| 159 | + $keys = $this->filterFuzzy( $keys, $condition ); |
| 160 | + } elseif ( $filter === 'hastranslation' ) { |
| 161 | + $keys = $this->filterHastranslation( $keys, $condition ); |
| 162 | + } elseif ( $filter === 'translated' ) { |
| 163 | + $fuzzy = $this->filterFuzzy( $keys, false ); |
| 164 | + $hastranslation = $this->filterHastranslation( $keys, false ); |
| 165 | + // Fuzzy messages are not translated messages |
| 166 | + $translated = $this->filterOnCondition( $hastranslation, $fuzzy ); |
| 167 | + $keys = $this->filterOnCondition( $keys, $translated, $condition ); |
| 168 | + } elseif( $filter === 'changed' ) { |
| 169 | + $keys = $this->filterChanged( $keys, $condition ); |
| 170 | + } else { // Filter based on tags |
| 171 | + if ( !isset($this->tags[$filter]) ) throw new MWException( "No tagged messages for filter $filter" ); |
| 172 | + $taggedKeys = array_flip( $this->tags[$filter] ); |
| 173 | + $keys = $this->filterOnCondition( $keys, $taggedKeys, $condition ); |
| 174 | + } |
| 175 | + $this->keys = $keys; |
| 176 | + } |
| 177 | + |
| 178 | + protected function filterOnCondition( array $keys, array $condKeys, $condition = true ) { |
| 179 | + if ( $condition === true ) { |
| 180 | + // Delete $condKeys from $keys |
| 181 | + foreach( array_keys($condKeys) as $key ) { |
| 182 | + unset($keys[$key]); |
| 183 | + } |
| 184 | + } else { |
| 185 | + // Keep the keys which are in $condKeys |
| 186 | + foreach( array_keys($keys) as $key ) { |
| 187 | + if ( !isset($condKeys[$key]) ) { |
| 188 | + unset($keys[$key]); |
| 189 | + } |
| 190 | + } |
| 191 | + } |
| 192 | + return $keys; |
| 193 | + } |
| 194 | + |
| 195 | + protected function filterFuzzy( array $keys, $condition ) { |
| 196 | + $this->loadInfo( $keys ); |
| 197 | + |
| 198 | + if ( $condition === false ) $origKeys = $keys; |
| 199 | + |
| 200 | + $fuzzy = array(); |
| 201 | + $flipKeys = array_flip( $keys ); |
| 202 | + foreach ( $this->dbInfo as $row ) { |
| 203 | + if ( $row->rt_type !== null ) { |
| 204 | + if ( !isset($flipKeys[$row->page_title]) ) continue; |
| 205 | + unset($keys[$flipKeys[$row->page_title]]); |
| 206 | + $fuzzy[] = $flipKeys[$row->page_title]; |
| 207 | + } |
| 208 | + } |
| 209 | + |
| 210 | + if ( !isset($this->tags['fuzzy']) ) |
| 211 | + $this->setTags( 'fuzzy', $fuzzy ); |
| 212 | + |
| 213 | + if ( $condition === false ) $keys = array_diff( $origKeys, $keys ); |
| 214 | + |
| 215 | + return $keys; |
| 216 | + } |
| 217 | + |
| 218 | + protected function filterHastranslation( array $keys, $condition ) { |
| 219 | + $this->loadInfo( $keys ); |
| 220 | + |
| 221 | + if ( $condition === false ) $origKeys = $keys; |
| 222 | + |
| 223 | + $flipKeys = array_flip( $keys ); |
| 224 | + foreach ( $this->dbInfo as $row ) { |
| 225 | + // Remove messages which have a translation from keys |
| 226 | + if ( !isset($flipKeys[$row->page_title]) ) continue; |
| 227 | + unset($keys[$flipKeys[$row->page_title]]); |
| 228 | + } |
| 229 | + |
| 230 | + // Check also if there is something in the file that is not yet in the db |
| 231 | + foreach ( array_keys($this->infile) as $inf ) { |
| 232 | + unset($keys[$inf]); |
| 233 | + } |
| 234 | + |
| 235 | + // Remove the messages which do not have a translation from the list |
| 236 | + if ( $condition === false ) $keys = array_diff( $origKeys, $keys ); |
| 237 | + |
| 238 | + return $keys; |
| 239 | + } |
| 240 | + |
| 241 | + protected function filterChanged( array $keys, $condition ) { |
| 242 | + $this->loadData( $keys ); |
| 243 | + |
| 244 | + if ( $condition === false ) $origKeys = $keys; |
| 245 | + $flipKeys = array_flip( $keys ); |
| 246 | + foreach ( $this->dbData as $row ) { |
| 247 | + $realKey = $flipKeys[$row->page_title]; |
| 248 | + if ( !isset($this->infile[$realKey]) ) continue; |
| 249 | + |
| 250 | + $text = Revision::getRevisionText( $row ); |
| 251 | + if ( $this->infile[$realKey] === $text ) { |
| 252 | + // Remove changed messages from the list |
| 253 | + unset($keys[$realKey]); |
| 254 | + } |
| 255 | + } |
| 256 | + |
| 257 | + // Remove the messages which have not changed from the list |
| 258 | + if ( $condition === false ) { |
| 259 | + $keys = $this->filterOnCondition( $keys, $origKeys, false ); |
| 260 | + } |
| 261 | + |
| 262 | + return $keys; |
| 263 | + } |
| 264 | + |
| 265 | + protected function fixKeys( array $keys ) { |
| 266 | + $newkeys = array(); |
| 267 | + $namespace = $this->definitions->namespace; |
| 268 | + $code = $this->code; |
| 269 | + foreach( $keys as $key ) { |
| 270 | + $title = Title::makeTitleSafe( $namespace, $key. '/' . $code ); |
| 271 | + $newkeys[$key] = $title->getDBKey(); |
| 272 | + } |
| 273 | + return $newkeys; |
| 274 | + } |
| 275 | + |
| 276 | + protected function loadInfo( array $keys ) { |
| 277 | + if ( $this->dbInfo !== null ) return; |
| 278 | + if ( !count($keys) ) return; |
| 279 | + |
| 280 | + $dbr = wfGetDB( DB_SLAVE ); |
| 281 | + |
| 282 | + static $id = null; |
| 283 | + if ( $id === null ) |
| 284 | + $id = $dbr->selectField( 'revtag_type', 'rtt_id', array( 'rtt_name' => 'fuzzy' ), __METHOD__ ); |
| 285 | + |
| 286 | + $tables = array( 'page', 'revtag' ); |
| 287 | + $fields = array( 'page_title', 'rt_type' ); |
| 288 | + $conds = array( |
| 289 | + 'page_namespace' => $this->definitions->namespace, |
| 290 | + 'page_title' => array_values( $keys ), |
| 291 | + ); |
| 292 | + $joins = array( 'revtag' => |
| 293 | + array( |
| 294 | + 'LEFT JOIN', |
| 295 | + array( 'page_id=rt_page', 'page_latest=rt_revision', 'rt_type' => $id ) |
| 296 | + ) |
| 297 | + ); |
| 298 | + |
| 299 | + $this->dbInfo = $dbr->select( $tables, $fields, $conds, __METHOD__, array(), $joins ); |
| 300 | + } |
| 301 | + |
| 302 | + protected function loadData( $keys ) { |
| 303 | + if ( $this->dbData !== null ) return; |
| 304 | + if ( !count($keys) ) return; |
| 305 | + |
| 306 | + $dbr = wfGetDB( DB_SLAVE ); |
| 307 | + |
| 308 | + $tables = array( 'page', 'revision', 'text' ); |
| 309 | + $fields = array( 'page_title', 'rev_user_text', 'old_flags', 'old_text' ); |
| 310 | + $conds = array( |
| 311 | + 'page_namespace' => $this->definitions->namespace, |
| 312 | + 'page_title' => array_values( $keys ), |
| 313 | + 'page_latest = rev_id', |
| 314 | + 'old_id = rev_text_id', |
| 315 | + ); |
| 316 | + |
| 317 | + $res = $dbr->select( $tables, $fields, $conds, __METHOD__ ); |
| 318 | + |
| 319 | + $this->dbData = $res; |
| 320 | + } |
| 321 | + |
| 322 | + public function initMessages() { |
| 323 | + if ( $this->messages !== null ) return; |
| 324 | + |
| 325 | + $messages = array(); |
| 326 | + |
| 327 | + foreach ( array_keys($this->keys) as $key ) { |
| 328 | + $messages[$key] = new ThinMessage( $key, $this->definitions->messages[$key] ); |
| 329 | + } |
| 330 | + |
| 331 | + // Copy rows if any |
| 332 | + if ( $this->dbData !== null ) { |
| 333 | + $flipKeys = array_flip( $this->keys ); |
| 334 | + foreach ( $this->dbData as $row ) { |
| 335 | + if ( !isset($flipKeys[$row->page_title]) ) continue; |
| 336 | + $key = $flipKeys[$row->page_title]; |
| 337 | + $messages[$key]->setRow( $row ); |
| 338 | + } |
| 339 | + } |
| 340 | + |
| 341 | + // Copy tags if any |
| 342 | + foreach ( $this->tags as $type => $keys ) { |
| 343 | + foreach( $keys as $key ) { |
| 344 | + if ( isset($messages[$key]) ) { |
| 345 | + $messages[$key]->setTag( $type ); |
| 346 | + } |
| 347 | + } |
| 348 | + } |
| 349 | + |
| 350 | + // Copy infile if any |
| 351 | + foreach ( $this->infile as $key => $value ) { |
| 352 | + if ( isset($messages[$key]) ) { |
| 353 | + $messages[$key]->setInfile( $value ); |
| 354 | + } |
| 355 | + } |
| 356 | + |
| 357 | + $this->messages = $messages; |
| 358 | + } |
| 359 | + |
| 360 | + // Interfaces etc. |
| 361 | + // |
| 362 | + /* ArrayAccess methods */ |
| 363 | + public function offsetExists( $offset ) { |
| 364 | + return isset( $this->messages[$offset] ); |
| 365 | + } |
| 366 | + |
| 367 | + public function offsetGet( $offset ) { |
| 368 | + return $this->messages[$offset]; |
| 369 | + } |
| 370 | + |
| 371 | + public function offsetSet( $offset, $value ) { |
| 372 | + throw new MWException( "Cannot add or modify elements" ); |
| 373 | + } |
| 374 | + |
| 375 | + public function offsetUnset( $offset ) { |
| 376 | + unset( $this->messages[$offset] ); |
| 377 | + } |
| 378 | + |
| 379 | + /* Fail fast */ |
| 380 | + public function __get( $name ) { |
| 381 | + throw new MWException( __METHOD__ . ": Trying to access unknown property $name" ); |
| 382 | + } |
| 383 | + |
| 384 | + /* Fail fast */ |
| 385 | + public function __set( $name, $value ) { |
| 386 | + throw new MWException( __METHOD__ . ": Trying to modify unknown property $name" ); |
| 387 | + } |
| 388 | + |
| 389 | + /* Iterator methods */ |
| 390 | + public function rewind() { |
| 391 | + reset( $this->messages ); |
| 392 | + } |
| 393 | + |
| 394 | + public function current() { |
| 395 | + if ( !count($this->messages) ) return false; |
| 396 | + return current($this->messages); |
| 397 | + } |
| 398 | + |
| 399 | + public function key() { |
| 400 | + return key( $this->messages ); |
| 401 | + } |
| 402 | + |
| 403 | + public function next() { |
| 404 | + return next( $this->messages ); |
| 405 | + } |
| 406 | + |
| 407 | + public function valid() { |
| 408 | + return $this->current() !== false; |
| 409 | + } |
| 410 | + |
| 411 | + public function count() { |
| 412 | + return count($this->keys()); |
| 413 | + } |
| 414 | + |
| 415 | +} |
| 416 | + |
| 417 | +class MessageDefinitions { |
| 418 | + public $namespace; |
| 419 | + public $messages; |
| 420 | + public function __construct( $namespace, array $messages ) { |
| 421 | + $this->namespace = $namespace; |
| 422 | + $this->messages = $messages; |
| 423 | + } |
| 424 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/Translate/MessageCollection.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 425 | + native |
Index: trunk/extensions/Translate/scripts/sync-group.php |
— | — | @@ -130,7 +130,7 @@ |
131 | 131 | if ( !count( $messages ) ) return; |
132 | 132 | |
133 | 133 | $collection = $this->group->initCollection( $code ); |
134 | | - $this->group->fillCollection( $collection ); |
| 134 | + $collection->loadTranslations(); |
135 | 135 | |
136 | 136 | foreach ( $messages as $key => $translation ) { |
137 | 137 | |
— | — | @@ -145,13 +145,13 @@ |
146 | 146 | |
147 | 147 | $page = $title->getPrefixedText(); |
148 | 148 | |
149 | | - if ( $collection[$key]->database === null ) { |
| 149 | + if ( $collection[$key]->translation() === null ) { |
150 | 150 | STDOUT( "Importing $page as a new translation" ); |
151 | 151 | $this->import( $title, $translation, 'Importing a new translation' ); |
152 | 152 | continue; |
153 | 153 | } |
154 | 154 | |
155 | | - $current = str_replace( TRANSLATE_FUZZY, '', $collection[$key]->translation ); |
| 155 | + $current = str_replace( TRANSLATE_FUZZY, '', $collection[$key]->translation() ); |
156 | 156 | $translation = str_replace( TRANSLATE_FUZZY, '', $translation ); |
157 | 157 | if ( $translation === $current ) continue; |
158 | 158 | |
Index: trunk/extensions/Translate/scripts/groupStatistics.php |
— | — | @@ -105,43 +105,70 @@ |
106 | 106 | } |
107 | 107 | $out->blockend(); |
108 | 108 | |
109 | | -// Perform the statistic calculations on every language |
| 109 | +$rows = array(); |
110 | 110 | foreach ( $languages as $code => $name ) { |
111 | 111 | // Skip list |
112 | 112 | if ( in_array( $code, $skipLanguages ) ) continue; |
| 113 | + $rows[$code] = array(); |
| 114 | +} |
113 | 115 | |
114 | | - // Tracker for skipping languages with no localisation |
115 | | - $allZero = true; |
116 | | - $columns = array(); |
| 116 | +$cache = new ArrayMemoryCache( 'groupstats' ); |
117 | 117 | |
118 | | - foreach ( $groups as $g ) { |
119 | | - // Initialise messages |
120 | | - $collection = $g->initCollection( $code ); |
121 | | - $collection->filter( 'optional' ); |
122 | | - // Store the count of real messages for later calculation. |
123 | | - $total = count( $collection ); |
| 118 | +foreach ( $groups as $groupName => $g ) { |
| 119 | + // Initialise messages |
| 120 | + $collection = $g->initCollection( 'en' ); |
124 | 121 | |
125 | | - // Fill translations in for counting |
126 | | - $g->fillCollection( $collection ); |
| 122 | + // Perform the statistic calculations on every language |
| 123 | + foreach ( $languages as $code => $name ) { |
| 124 | + // Skip list |
| 125 | + if ( in_array( $code, $skipLanguages ) ) continue; |
127 | 126 | |
128 | | - // Count fuzzy first |
129 | | - $collection->filter( 'fuzzy' ); |
130 | | - $fuzzy = $total - count( $collection ); |
| 127 | + $incache = $cache->get( $groupName, $code ); |
| 128 | + if ( $incache !== false ) { |
| 129 | + list( $fuzzy, $translated, $total ) = $incache; |
| 130 | + } else { |
131 | 131 | |
132 | | - // Count the completion percent |
133 | | - $collection->filter( 'translated', false ); |
134 | | - $translated = count( $collection ); |
135 | | - if ( $translated ) $allZero = false; |
| 132 | + $collection->resetForNewLanguage( $code ); |
| 133 | + $collection->filter( 'ignored' ); |
| 134 | + $collection->filter( 'optional' ); |
| 135 | + // Store the count of real messages for later calculation. |
| 136 | + $total = count( $collection ); |
136 | 137 | |
137 | | - $columns[] = $out->formatPercent( $translated, $total, |
138 | | - /* Inverted color */ false, /* Decimals */ 2 ); |
| 138 | + // Count fuzzy first |
| 139 | + $collection->filter( 'fuzzy' ); |
| 140 | + $fuzzy = $total - count( $collection ); |
139 | 141 | |
| 142 | + // Count the completion percent |
| 143 | + $collection->filter( 'hastranslation', false ); |
| 144 | + $translated = count( $collection ); |
| 145 | + |
| 146 | + $cache->set( $groupName, $code, array( $fuzzy, $translated, $total ) ); |
| 147 | + } |
| 148 | + |
| 149 | + $rows[$code][] = array( $translated, $total ); |
| 150 | + |
140 | 151 | if ( isset( $options['fuzzy'] ) ) { |
141 | | - $columns[] = $out->formatPercent( $fuzzy, $total, |
142 | | - /* Inverted color */ true, /* Decimals */ 2 ); |
| 152 | + $rows[$code][] = array( $fuzzy, $total ); |
143 | 153 | } |
| 154 | + |
144 | 155 | } |
145 | 156 | |
| 157 | + $cache->commit(); // Don't keep open too long... to avoid concurrent access |
| 158 | + |
| 159 | + unset($collection); |
| 160 | +} |
| 161 | + |
| 162 | +foreach ( $languages as $code => $name ) { |
| 163 | + // Skip list |
| 164 | + if ( in_array( $code, $skipLanguages ) ) continue; |
| 165 | + |
| 166 | + $columns = $rows[$code]; |
| 167 | + |
| 168 | + $allZero = true; |
| 169 | + foreach ( $columns as $fields ) { |
| 170 | + if ( $fields[0] !== 0 ) $allZero = false; |
| 171 | + } |
| 172 | + |
146 | 173 | // Skip dummy languages if requested |
147 | 174 | if ( $allZero && isset( $options['skipzero'] ) ) continue; |
148 | 175 | |
— | — | @@ -149,7 +176,11 @@ |
150 | 177 | $out->blockstart(); |
151 | 178 | $out->element( $code ); |
152 | 179 | $out->element( $name ); |
153 | | - foreach ( $columns as $c ) $out->element( $c ); |
| 180 | + foreach ( $columns as $fields ) { |
| 181 | + list( $upper, $total ) = $fields; |
| 182 | + $c = $out->formatPercent( $upper, $total, /* Inverted color */ false, /* Decimals */ 2 ); |
| 183 | + $out->element( $c ); |
| 184 | + } |
154 | 185 | $out->blockend(); |
155 | 186 | } |
156 | 187 | |
Index: trunk/extensions/Translate/scripts/createCheckIndex.php |
— | — | @@ -60,13 +60,11 @@ |
61 | 61 | foreach ( $codes as $code ) { |
62 | 62 | STDOUT( "$code ", $id ); |
63 | 63 | |
64 | | - $collection = clone $collection_skel; |
65 | | - $collection->code = $code; |
| 64 | + $collection->reset( $code ); |
| 65 | + $collection->loadTranslations(); |
66 | 66 | |
67 | | - $g->fillCollection( $collection ); |
68 | | - |
69 | | - foreach ( $collection->keys() as $key ) { |
70 | | - $prob = $checker->doFastChecks( $collection[$key], $type, $code ); |
| 67 | + foreach ( $collection as $key => $message ) { |
| 68 | + $prob = $checker->doFastChecks( $message, $type, $code ); |
71 | 69 | if ( $prob ) { |
72 | 70 | |
73 | 71 | if ( $verbose ) { |
Index: trunk/extensions/Translate/scripts/autoexport.php |
— | — | @@ -111,6 +111,8 @@ |
112 | 112 | sort( $languages ); |
113 | 113 | $languages = checkThreshold( $group, $languages, $threshold ); |
114 | 114 | |
| 115 | + if ( !count($languages) ) continue; |
| 116 | + |
115 | 117 | $languagelist = implode( ', ', $languages ); |
116 | 118 | STDOUT( str_replace( |
117 | 119 | array( '$GROUP', '$LANG', '$TARGET' ), |
— | — | @@ -135,17 +137,10 @@ |
136 | 138 | foreach ( $languages as $code ) { |
137 | 139 | // Initialise messages |
138 | 140 | $collection = $g->initCollection( $code ); |
| 141 | + $collection->filter( 'ignored' ); |
139 | 142 | $collection->filter( 'optional' ); |
140 | 143 | // Store the count of real messages for later calculation. |
141 | 144 | $total = count( $collection ); |
142 | | - |
143 | | - // Fill translations in for counting |
144 | | - $g->fillCollection( $collection ); |
145 | | - |
146 | | - // Count fuzzy first |
147 | | - $collection->filter( 'fuzzy' ); |
148 | | - |
149 | | - // Count the completion percent |
150 | 145 | $collection->filter( 'translated', false ); |
151 | 146 | $translated = count( $collection ); |
152 | 147 | |
Index: trunk/extensions/Translate/TranslateTasks.php |
— | — | @@ -72,7 +72,15 @@ |
73 | 73 | } |
74 | 74 | |
75 | 75 | protected $process = array(); |
76 | | - abstract protected function setProcess(); |
| 76 | + |
| 77 | + protected function setProcess() { |
| 78 | + $this->process = array( |
| 79 | + array( $this, 'preinit' ), |
| 80 | + array( $this, 'doPaging' ), |
| 81 | + array( $this, 'postinit' ), |
| 82 | + ); |
| 83 | + } |
| 84 | + |
77 | 85 | abstract protected function output(); |
78 | 86 | |
79 | 87 | public final function execute() { |
— | — | @@ -85,14 +93,12 @@ |
86 | 94 | |
87 | 95 | protected function doPaging() { |
88 | 96 | $total = count( $this->collection ); |
89 | | - |
90 | 97 | $this->collection->slice( |
91 | 98 | $this->options->getOffset(), |
92 | 99 | $this->options->getLimit() |
93 | 100 | ); |
| 101 | + $left = count( $this->collection ); |
94 | 102 | |
95 | | - $left = count( $this->collection ); |
96 | | - |
97 | 103 | $callback = $this->options->getPagingCB(); |
98 | 104 | call_user_func( $callback, $this->options->getOffset(), $left, $total ); |
99 | 105 | } |
— | — | @@ -101,26 +107,15 @@ |
102 | 108 | class ViewMessagesTask extends TranslateTask { |
103 | 109 | protected $id = 'view'; |
104 | 110 | |
105 | | - protected function setProcess() { |
106 | | - $this->process = array( |
107 | | - array( $this, 'preinit' ), |
108 | | - array( $this, 'filterOptional' ), |
109 | | - array( $this, 'doPaging' ), |
110 | | - array( $this, 'postinit' ), |
111 | | - ); |
112 | | - } |
113 | | - |
114 | 111 | protected function preinit() { |
115 | 112 | $code = $this->options->getLanguage(); |
116 | 113 | $this->collection = $this->group->initCollection( $code ); |
117 | | - } |
118 | | - |
119 | | - protected function filterOptional() { |
| 114 | + $this->collection->filter( 'ignored' ); |
120 | 115 | $this->collection->filter( 'optional' ); |
121 | 116 | } |
122 | 117 | |
123 | 118 | protected function postinit() { |
124 | | - $this->group->fillCollection( $this->collection ); |
| 119 | + $this->collection->loadTranslations(); |
125 | 120 | } |
126 | 121 | |
127 | 122 | protected function output() { |
— | — | @@ -131,26 +126,45 @@ |
132 | 127 | |
133 | 128 | } |
134 | 129 | |
135 | | -class ViewUntranslatedTask extends ViewMessagesTask { |
136 | | - protected $id = 'untranslated'; |
| 130 | +class ReviewMessagesTask extends ViewMessagesTask { |
| 131 | + protected $id = 'review'; |
137 | 132 | |
138 | | - protected function setProcess() { |
139 | | - $this->process = array( |
140 | | - array( $this, 'preinit' ), |
141 | | - array( $this, 'filterOptional' ), |
142 | | - array( $this, 'postinit' ), |
143 | | - array( $this, 'filterTranslated' ), |
144 | | - array( $this, 'doPaging' ), |
145 | | - ); |
| 133 | + protected function preinit() { |
| 134 | + $code = $this->options->getLanguage(); |
| 135 | + $this->collection = $this->group->initCollection( $code ); |
| 136 | + $this->collection->setInfile( $this->group->load( $code ) ); |
| 137 | + $this->collection->filter( 'ignored' ); |
| 138 | + $this->collection->filter( 'changed', false ); |
146 | 139 | } |
147 | 140 | |
148 | | - /** |
149 | | - * Filters all translated messages. Fuzzy messages are not considered to be |
150 | | - * translated, because they need attention from translators. Also optional |
151 | | - * messages can not have identical translations. |
152 | | - */ |
153 | | - protected function filterTranslated() { |
| 141 | + protected function output() { |
| 142 | + $table = new MessageTable( $this->collection, $this->group ); |
| 143 | + $table->appendEditLinkParams( 'loadtask', $this->getId() ); |
| 144 | + $table->setReviewMode(); |
| 145 | + |
| 146 | + return $table->fullTable(); |
| 147 | + } |
| 148 | + |
| 149 | +} |
| 150 | + |
| 151 | +class ViewUntranslatedTask extends ReviewMessagesTask { |
| 152 | + protected $id = 'untranslated'; |
| 153 | + |
| 154 | + protected function preinit() { |
| 155 | + $code = $this->options->getLanguage(); |
| 156 | + $this->collection = $this->group->initCollection( $code ); |
| 157 | + $this->collection->setInfile( $this->group->load( $code ) ); |
| 158 | + $this->collection->filter( 'ignored' ); |
| 159 | + $this->collection->filter( 'optional' ); |
| 160 | + |
| 161 | + // Update the cache while we are at it |
| 162 | + $total = count($this->collection); |
154 | 163 | $this->collection->filter( 'translated' ); |
| 164 | + $translated = $total - count($this->collection); |
| 165 | + $fuzzy = count($this->collection->getTags('fuzzy')); |
| 166 | + |
| 167 | + $cache = new ArrayMemoryCache( 'groupstats' ); |
| 168 | + $cache->set( $this->group->getID(), $code, array( $fuzzy, $translated, $total ) ); |
155 | 169 | } |
156 | 170 | |
157 | 171 | } |
— | — | @@ -161,13 +175,16 @@ |
162 | 176 | protected function setProcess() { |
163 | 177 | $this->process = array( |
164 | 178 | array( $this, 'preinit' ), |
165 | | - array( $this, 'filterNonOptional' ), |
166 | 179 | array( $this, 'doPaging' ), |
167 | 180 | array( $this, 'postinit' ), |
168 | 181 | ); |
169 | 182 | } |
170 | 183 | |
171 | | - protected function filterNonOptional() { |
| 184 | + protected function preinit() { |
| 185 | + $code = $this->options->getLanguage(); |
| 186 | + $this->collection = $this->group->initCollection( $code ); |
| 187 | + $this->collection->setInfile( $this->group->load( $code ) ); |
| 188 | + $this->collection->filter( 'ignored' ); |
172 | 189 | $this->collection->filter( 'optional', false ); |
173 | 190 | } |
174 | 191 | |
— | — | @@ -179,90 +196,38 @@ |
180 | 197 | protected function setProcess() { |
181 | 198 | $this->process = array( |
182 | 199 | array( $this, 'preinit' ), |
183 | | - array( $this, 'filterNonOptional' ), |
184 | | - array( $this, 'postinit' ), |
185 | | - array( $this, 'filterTranslated' ), |
186 | 200 | array( $this, 'doPaging' ), |
187 | | - ); |
188 | | - } |
189 | | - |
190 | | - protected function filterTranslated() { |
191 | | - $this->collection->filter( 'translated' ); |
192 | | - } |
193 | | - |
194 | | -} |
195 | | - |
196 | | -class ViewProblematicTask extends ReviewMessagesTask { |
197 | | - protected $id = 'problematic'; |
198 | | - |
199 | | - protected function setProcess() { |
200 | | - $this->process = array( |
201 | | - array( $this, 'preinit' ), |
202 | 201 | array( $this, 'postinit' ), |
203 | | - array( $this, 'filterNonProblematic' ), |
204 | | - array( $this, 'doPaging' ), |
205 | 202 | ); |
206 | 203 | } |
207 | 204 | |
208 | | - protected function filterNonProblematic() { |
| 205 | + protected function preinit() { |
209 | 206 | $code = $this->options->getLanguage(); |
210 | | - $problematic = $this->group->getProblematic( $code ); |
211 | | - $checker = MessageChecks::getInstance(); |
212 | | - $type = $this->group->getType(); |
213 | | - |
214 | | - foreach ( $this->collection->keys() as $key ) { |
215 | | - $item = $this->collection[$key]; |
216 | | - if ( in_array( $key, $problematic ) ) { |
217 | | - if ( $checker->doFastChecks( $item, $type, $code ) ) continue; |
218 | | - } |
219 | | - |
220 | | - unset( $this->collection[$key] ); |
221 | | - } |
| 207 | + $this->collection = $this->group->initCollection( $code ); |
| 208 | + $this->collection->setInfile( $this->group->load( $code ) ); |
| 209 | + $this->collection->filter( 'ignored' ); |
| 210 | + $this->collection->filter( 'optional', false ); |
| 211 | + $this->collection->filter( 'translated' ); |
222 | 212 | } |
223 | | - |
224 | 213 | } |
225 | 214 | |
226 | | - |
227 | | -class ReviewMessagesTask extends ViewMessagesTask { |
228 | | - protected $id = 'review'; |
229 | | - |
230 | | - protected function setProcess() { |
231 | | - $this->process = array( |
232 | | - array( $this, 'preinit' ), |
233 | | - array( $this, 'postinit' ), |
234 | | - array( $this, 'filterUnchanged' ), |
235 | | - array( $this, 'doPaging' ), |
236 | | - ); |
237 | | - } |
238 | | - |
239 | | - protected function filterUnchanged() { |
240 | | - $this->collection->filter( 'changed', false ); |
241 | | - } |
242 | | - |
243 | | - protected function output() { |
244 | | - $table = new MessageTable( $this->collection, $this->group ); |
245 | | - $table->appendEditLinkParams( 'loadtask', $this->getId() ); |
246 | | - $table->setReviewMode(); |
247 | | - |
248 | | - return $table->fullTable(); |
249 | | - } |
250 | | - |
251 | | -} |
252 | | - |
253 | 215 | class ReviewAllMessagesTask extends ReviewMessagesTask { |
254 | 216 | protected $id = 'reviewall'; |
255 | 217 | |
256 | 218 | protected function setProcess() { |
257 | 219 | $this->process = array( |
258 | 220 | array( $this, 'preinit' ), |
259 | | - array( $this, 'postinit' ), |
260 | | - array( $this, 'filterUntranslated' ), |
261 | 221 | array( $this, 'doPaging' ), |
| 222 | + array( $this, 'postinit' ), |
262 | 223 | ); |
263 | 224 | } |
264 | 225 | |
265 | | - protected function filterUntranslated() { |
266 | | - $this->collection->filter( 'translated', false ); |
| 226 | + protected function preinit() { |
| 227 | + $code = $this->options->getLanguage(); |
| 228 | + $this->collection = $this->group->initCollection( $code ); |
| 229 | + $this->collection->setInfile( $this->group->load( $code ) ); |
| 230 | + $this->collection->filter( 'ignored' ); |
| 231 | + $this->collection->filter( 'hastranslation', false ); |
267 | 232 | } |
268 | 233 | |
269 | 234 | } |
— | — | @@ -297,7 +262,7 @@ |
298 | 263 | |
299 | 264 | public function output() { |
300 | 265 | $writer = $this->group->getWriter(); |
301 | | - $this->collection->filter( 'translation', null ); |
| 266 | + $this->collection->filter( 'translated', false ); |
302 | 267 | return $writer->webExport( $this->collection ); |
303 | 268 | } |
304 | 269 | } |
— | — | @@ -356,12 +321,12 @@ |
357 | 322 | foreach ( $this->collection as $key => $m ) { |
358 | 323 | $flags = array(); |
359 | 324 | |
360 | | - $translation = $m->translation; |
| 325 | + $translation = $m->translation(); |
361 | 326 | # CASE2: no translation |
362 | 327 | if ( $translation === null ) $translation = ''; |
363 | 328 | |
364 | 329 | # CASE3: optional messages; accept only if different |
365 | | - if ( $m->optional ) $flags[] = 'optional'; |
| 330 | + if ( $m->hasTag( 'optional') ) $flags[] = 'optional'; |
366 | 331 | |
367 | 332 | # Remove fuzzy markings before export |
368 | 333 | if ( strpos( $translation, TRANSLATE_FUZZY ) !== false ) { |
— | — | @@ -376,7 +341,7 @@ |
377 | 342 | } |
378 | 343 | |
379 | 344 | $out .= self::formatcomments( $comments, $flags ); |
380 | | - $out .= self::formatmsg( $m->definition, $translation, $key, $flags ); |
| 345 | + $out .= self::formatmsg( $m->definition(), $translation, $key, $flags ); |
381 | 346 | |
382 | 347 | } |
383 | 348 | |
Index: trunk/extensions/Translate/MessageChecks.php |
— | — | @@ -69,7 +69,7 @@ |
70 | 70 | * @return Array of warning messages, html-format. |
71 | 71 | */ |
72 | 72 | public function doChecks( TMessage $message, $type, $code ) { |
73 | | - if ( $message->translation === null ) return array(); |
| 73 | + if ( $message->translation() === null ) return array(); |
74 | 74 | $warnings = array(); |
75 | 75 | |
76 | 76 | foreach ( $this->checksForType[$type] as $check ) { |
— | — | @@ -83,7 +83,7 @@ |
84 | 84 | } |
85 | 85 | |
86 | 86 | public function doFastChecks( TMessage $message, $type, $code ) { |
87 | | - if ( $message->translation === null ) return false; |
| 87 | + if ( $message->translation() === null ) return false; |
88 | 88 | |
89 | 89 | foreach ( $this->checksForType[$type] as $check ) { |
90 | 90 | if ( $this->$check( $message, $code ) ) return true; |
— | — | @@ -103,8 +103,8 @@ |
104 | 104 | $variables = array( '\$1', '\$2', '\$3', '\$4', '\$5', '\$6', '\$7', '\$8', '\$9' ); |
105 | 105 | |
106 | 106 | $missing = array(); |
107 | | - $definition = $message->definition; |
108 | | - $translation = $message->translation; |
| 107 | + $definition = $message->definition(); |
| 108 | + $translation = $message->translation(); |
109 | 109 | if ( strpos( $definition, '$' ) === false ) return false; |
110 | 110 | |
111 | 111 | for ( $i = 1; $i < 10; $i++ ) { |
— | — | @@ -129,8 +129,8 @@ |
130 | 130 | $variables = array( '\$1', '\$2', '\$3', '\$4', '\$5', '\$6', '\$7', '\$8', '\$9' ); |
131 | 131 | |
132 | 132 | $missing = array(); |
133 | | - $definition = $message->definition; |
134 | | - $translation = $message->translation; |
| 133 | + $definition = $message->definition(); |
| 134 | + $translation = $message->translation(); |
135 | 135 | if ( strpos( $translation, '$' ) === false ) return false; |
136 | 136 | |
137 | 137 | for ( $i = 1; $i < 10; $i++ ) { |
— | — | @@ -160,7 +160,7 @@ |
161 | 161 | * and closing count as value. |
162 | 162 | */ |
163 | 163 | protected function checkBalance( TMessage $message, $code, &$desc = null ) { |
164 | | - $translation = preg_replace( '/[^{}[\]()]/u', '', $message->translation ); |
| 164 | + $translation = preg_replace( '/[^{}[\]()]/u', '', $message->translation() ); |
165 | 165 | $counts = array( '{' => 0, '}' => 0, '[' => 0, ']' => 0, '(' => 0, ')' => 0 ); |
166 | 166 | |
167 | 167 | $i = 0; |
— | — | @@ -197,12 +197,12 @@ |
198 | 198 | * @return Array of problematic links. |
199 | 199 | */ |
200 | 200 | protected function checkLinks( TMessage $message, $code, &$desc = null ) { |
201 | | - if ( strpos( $message->translation, '[[' ) === false ) return false; |
| 201 | + if ( strpos( $message->translation(), '[[' ) === false ) return false; |
202 | 202 | |
203 | 203 | $matches = array(); |
204 | 204 | $links = array(); |
205 | 205 | $tc = Title::legalChars() . '#%{}'; |
206 | | - preg_match_all( "/\[\[([{$tc}]+)(?:\\|(.+?))?]]/sDu", $message->translation, $matches ); |
| 206 | + preg_match_all( "/\[\[([{$tc}]+)(?:\\|(.+?))?]]/sDu", $message->translation(), $matches ); |
207 | 207 | for ( $i = 0; $i < count( $matches[0] ); $i++ ) { |
208 | 208 | // if ( preg_match( '/({{ns:)?special(}})?:.*/sDui', $matches[1][$i] ) ) continue; |
209 | 209 | // if ( preg_match( '/{{mediawiki:.*}}/sDui', $matches[1][$i] ) ) continue; |
— | — | @@ -210,7 +210,7 @@ |
211 | 211 | // if ( preg_match( '/:?\$[1-9]/sDu', $matches[1][$i] ) ) continue; |
212 | 212 | |
213 | 213 | $backMatch = preg_quote( $matches[1][$i], '/' ); |
214 | | - if ( preg_match( "/$backMatch/", $message->definition ) ) continue; |
| 214 | + if ( preg_match( "/$backMatch/", $message->definition() ) ) continue; |
215 | 215 | |
216 | 216 | $links[] = "[[{$matches[1][$i]}|{$matches[2][$i]}]]"; |
217 | 217 | } |
— | — | @@ -234,7 +234,7 @@ |
235 | 235 | * value. |
236 | 236 | */ |
237 | 237 | protected function checkXHTML( TMessage $message, $code, &$desc = null ) { |
238 | | - $translation = $message->translation; |
| 238 | + $translation = $message->translation(); |
239 | 239 | if ( strpos( $translation, '<' ) === false ) return false; |
240 | 240 | |
241 | 241 | $tags = array( |
— | — | @@ -277,8 +277,8 @@ |
278 | 278 | && in_array( 'plural', $this->blacklist[$code] ) ) |
279 | 279 | return false; |
280 | 280 | |
281 | | - $definition = $message->definition; |
282 | | - $translation = $message->translation; |
| 281 | + $definition = $message->definition(); |
| 282 | + $translation = $message->translation(); |
283 | 283 | if ( stripos( $definition, '{{plural:' ) !== false && |
284 | 284 | stripos( $translation, '{{plural:' ) === false ) { |
285 | 285 | $desc = array( 'translate-checks-plural' ); |
— | — | @@ -295,8 +295,8 @@ |
296 | 296 | * @return True if namespace has been tampered with. |
297 | 297 | */ |
298 | 298 | protected function checkPagename( TMessage $message, $code, &$desc = null ) { |
299 | | - $definition = $message->definition; |
300 | | - $translation = $message->translation; |
| 299 | + $definition = $message->definition(); |
| 300 | + $translation = $message->translation(); |
301 | 301 | |
302 | 302 | $namespaces = 'help|project|\{\{ns:project}}|mediawiki'; |
303 | 303 | $matches = array(); |
— | — | @@ -317,9 +317,9 @@ |
318 | 318 | */ |
319 | 319 | protected function miscMWChecks( TMessage $message, $code, &$desc = null ) { |
320 | 320 | $timeList = array( 'protect-expiry-options', 'ipboptions' ); |
321 | | - if ( in_array( strtolower($message->key), $timeList, true ) ) { |
322 | | - $defArray = explode( ',', $message->definition ); |
323 | | - $traArray = explode( ',', $message->translation ); |
| 321 | + if ( in_array( strtolower($message->key()), $timeList, true ) ) { |
| 322 | + $defArray = explode( ',', $message->definition() ); |
| 323 | + $traArray = explode( ',', $message->translation() ); |
324 | 324 | |
325 | 325 | $defCount = count($defArray); |
326 | 326 | $traCount = count($traArray); |
— | — | @@ -353,10 +353,10 @@ |
354 | 354 | protected function checkFreeColMissingVars( TMessage $message, $code, &$desc = null ) { |
355 | 355 | $varPattern = '%[a-zA-Z_]+%'; |
356 | 356 | |
357 | | - if ( !preg_match_all( "/$varPattern/U", $message->definition, $defVars ) ) { |
| 357 | + if ( !preg_match_all( "/$varPattern/U", $message->definition(), $defVars ) ) { |
358 | 358 | return false; |
359 | 359 | } |
360 | | - preg_match_all( "/$varPattern/U", $message->translation, $transVars ); |
| 360 | + preg_match_all( "/$varPattern/U", $message->translation(), $transVars ); |
361 | 361 | |
362 | 362 | $missing = self::compareArrays( $defVars[0], $transVars[0] ); |
363 | 363 | |
— | — | @@ -381,8 +381,8 @@ |
382 | 382 | protected function checkFreeColExtraVars( TMessage $message, $code, &$desc = null ) { |
383 | 383 | $varPattern = '%[a-zA-Z_]+%'; |
384 | 384 | |
385 | | - preg_match_all( "/$varPattern/U", $message->definition, $defVars ); |
386 | | - preg_match_all( "/$varPattern/U", $message->translation, $transVars ); |
| 385 | + preg_match_all( "/$varPattern/U", $message->definition(), $defVars ); |
| 386 | + preg_match_all( "/$varPattern/U", $message->translation(), $transVars ); |
387 | 387 | |
388 | 388 | $missing = self::compareArrays( $transVars[0], $defVars[0] ); |
389 | 389 | |
— | — | @@ -399,7 +399,7 @@ |
400 | 400 | |
401 | 401 | protected function checkFreeColEscapes( TMessage $message, $code, &$desc = null ) { |
402 | 402 | $varPattern = '\\\\[^nt\'"]'; |
403 | | - preg_match_all( "/$varPattern/U", $message->translation, $transVars ); |
| 403 | + preg_match_all( "/$varPattern/U", $message->translation(), $transVars ); |
404 | 404 | |
405 | 405 | if ( $count = count( $transVars[0] ) ) { |
406 | 406 | global $wgLang; |
— | — | @@ -419,10 +419,10 @@ |
420 | 420 | * @return True if namespace has been tampered with. |
421 | 421 | */ |
422 | 422 | protected function checkPrintfMissingVars( TMessage $message, $code, &$desc = null ) { |
423 | | - if ( !preg_match_all( '/%[sd]/U', $message->definition, $defVars ) ) { |
| 423 | + if ( !preg_match_all( '/%[sd]/U', $message->definition(), $defVars ) ) { |
424 | 424 | return false; |
425 | 425 | } |
426 | | - preg_match_all( '/%[sd]/U', $message->translation, $transVars ); |
| 426 | + preg_match_all( '/%[sd]/U', $message->translation(), $transVars ); |
427 | 427 | |
428 | 428 | $missing = self::compareArrays( $defVars[0], $transVars[0] ); |
429 | 429 | |
— | — | @@ -445,8 +445,8 @@ |
446 | 446 | * @return True if namespace has been tampered with. |
447 | 447 | */ |
448 | 448 | protected function checkPrintfExtraVars( TMessage $message, $code, &$desc = null ) { |
449 | | - preg_match_all( '/%[sd]/U', $message->definition, $defVars ); |
450 | | - preg_match_all( '/%[sd]/U', $message->translation, $transVars ); |
| 449 | + preg_match_all( '/%[sd]/U', $message->definition(), $defVars ); |
| 450 | + preg_match_all( '/%[sd]/U', $message->translation(), $transVars ); |
451 | 451 | |
452 | 452 | $missing = self::compareArrays( $transVars[0], $defVars[0] ); |
453 | 453 | |
— | — | @@ -469,10 +469,10 @@ |
470 | 470 | * @return True if namespace has been tampered with. |
471 | 471 | */ |
472 | 472 | protected function checkI18nSprintMissingVars( TMessage $message, $code, &$desc = null ) { |
473 | | - if ( !preg_match_all( '/%[^% ]+/U', $message->definition, $defVars ) ) { |
| 473 | + if ( !preg_match_all( '/%[^% ]+/U', $message->definition(), $defVars ) ) { |
474 | 474 | return false; |
475 | 475 | } |
476 | | - preg_match_all( '/%[^% ]+/U', $message->translation, $transVars ); |
| 476 | + preg_match_all( '/%[^% ]+/U', $message->translation(), $transVars ); |
477 | 477 | |
478 | 478 | $missing = self::compareArrays( $defVars[0], $transVars[0] ); |
479 | 479 | |
— | — | @@ -495,8 +495,8 @@ |
496 | 496 | * @return True if namespace has been tampered with. |
497 | 497 | */ |
498 | 498 | protected function checkI18nSprintExtraVars( TMessage $message, $code, &$desc = null ) { |
499 | | - preg_match_all( '/%[^% ]+/U', $message->definition, $defVars ); |
500 | | - preg_match_all( '/%[^% ]+/U', $message->translation, $transVars ); |
| 499 | + preg_match_all( '/%[^% ]+/U', $message->definition(), $defVars ); |
| 500 | + preg_match_all( '/%[^% ]+/U', $message->translation(), $transVars ); |
501 | 501 | |
502 | 502 | $missing = self::compareArrays( $transVars[0], $defVars[0] ); |
503 | 503 | |
Index: trunk/extensions/Translate/TranslateUtils.php |
— | — | @@ -36,35 +36,6 @@ |
37 | 37 | return array( $key, $code ); |
38 | 38 | } |
39 | 39 | |
40 | | - /** |
41 | | - * Fills the actual translation from database, if any. |
42 | | - * |
43 | | - * @param $messages MessageCollection |
44 | | - * @param $namespaces Array: two-item 1-d array with namespace numbers |
45 | | - */ |
46 | | - public static function fillContents( MessageCollection $messages, |
47 | | - array $namespaces ) { |
48 | | - |
49 | | - $titles = array(); |
50 | | - foreach ( $messages->keys() as $key ) { |
51 | | - $titles[] = self::title( $key, $messages->code ); |
52 | | - } |
53 | | - |
54 | | - if ( !count( $titles ) ) return; |
55 | | - |
56 | | - // Fetch contents |
57 | | - $titles = self::getContents( $titles, $namespaces[0] ); |
58 | | - |
59 | | - foreach ( $messages->keys() as $key ) { |
60 | | - $title = self::title( $key, $messages->code ); |
61 | | - if ( isset( $titles[$title] ) ) { |
62 | | - $messages[$key]->database = $titles[$title][0]; |
63 | | - $messages[$key]->addAuthor( $titles[$title][1] ); |
64 | | - } |
65 | | - } |
66 | | - |
67 | | - } |
68 | | - |
69 | 40 | public static function getMessageContent( $key, $language, |
70 | 41 | $namespace = NS_MEDIAWIKI ) { |
71 | 42 | |