Rewrite reassignEdits script to be more efficient; support optional updates to recent...
[lhc/web/wiklou.git] / maintenance / transstat.php
1 <?php
2 /**
3 * @package MediaWiki
4 * @subpackage Maintenance
5 *
6 * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
7 * @author Ashar Voultoiz <thoane@altern.org>
8 * @bug 2499
9 *
10 * Output is posted from time to time on:
11 * http://meta.wikimedia.org/wiki/Localization_statistics
12 */
13
14 /** */
15 require_once('commandLine.inc');
16 require_once('languages.inc');
17
18 if( isset($options['help']) ) { usage(); wfDie(); }
19 // default output is WikiText
20 if( !isset($options['output']) ) { $options['output']='wiki'; }
21
22
23 /** Print a usage message*/
24 function usage() {
25 print <<<END
26 Usage: php transstat.php [--help] [--output:csv|text|wiki] [--showdupes]
27 --help : this helpful message
28 --showold : show old messages that are not in Messages.php
29 --output : select an output engine one of:
30 * 'csv' : Comma Separated Values.
31 * 'none' : Nothing, usefull with --showdupes
32 * 'wiki' : MediaWiki syntax (default).
33 * 'text' : Text with tabs.
34 Example: php transstat.php --showdupes --output=none
35
36
37 END;
38 }
39
40
41 /** A general output object. Need to be overriden */
42 class statsOutput {
43 var $output; // buffer that contain the text
44 function statsOutput() { $this->output='';}
45 function getContent() { return $this->output;}
46
47 function formatPercent($subset, $total, $revert=false, $accuracy=2) {
48 return @sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total );
49 }
50
51 // Override the next methods
52 function heading() {}
53 function footer() {}
54 function blockstart() {}
55 function blockend() {}
56 function element($in, $heading=false) {}
57 }
58
59 /** Outputs nothing ! */
60 class noneStatsOutput extends statsOutput {
61 function getContent() { return NULL;}
62 }
63
64 /** Outputs WikiText */
65 class wikiStatsOutput extends statsOutput {
66 function heading() {
67 $this->output .= "{| border=2 cellpadding=4 cellspacing=0 style=\"background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse;\" width=100%\n";
68 }
69 function footer() { $this->output .= "|}\n"; }
70 function blockstart() { $this->output .= "|-\n"; }
71 function blockend() { $this->output .= ''; }
72 function element($in, $heading = false) {
73 $this->output .= ($heading ? '!' : '|') . " $in\n";
74 }
75 function formatPercent($subset, $total, $revert=false, $accuracy=2) {
76 $v = @round(255 * $subset / $total);
77 if($revert) $v = 255 - $v;
78 if($v < 128) {
79 // red to yellow
80 $red = 'FF';
81 $green = sprintf('%02X', 2*$v);
82 } else {
83 // yellow to green
84 $red = sprintf('%02X', 2*(255 -$v) );
85 $green = 'FF';
86 }
87 $blue = '00';
88 $color = $red.$green.$blue;
89
90 $percent = statsOutput::formatPercent($subset, $total, $revert, $accuracy);
91 return 'bgcolor="#'.$color.'" | '.$percent;
92 }
93 }
94
95 /** Output text. To be used on a terminal for example. */
96 class textStatsOutput extends statsOutput {
97 function element($in, $heading = false) {
98 $this->output .= $in."\t";
99 }
100 function blockend(){ $this->output .="\n";}
101 }
102
103 /** csv output. Some people love excel */
104 class csvStatsOutput extends statsOutput {
105 function element($in, $heading = false) {
106 $this->output .= $in.";";
107 }
108 function blockend(){ $this->output .="\n";}
109 }
110
111
112 function redundant(&$arr, $langcode) {
113 global $wgAllMessagesEn;
114
115 $redundant = 0;
116 foreach(array_keys($arr) as $key) {
117 if ( @$wgAllMessagesEn[$key] === null ) {
118 global $options;
119 if( isset($options['showold']) ) {
120 print "Deprecated [$langcode]: $key\n";
121 }
122 ++$redundant;
123 }
124 }
125 return $redundant;
126 }
127
128 // Select an output engine
129 switch ($options['output']) {
130 case 'csv':
131 $out = new csvStatsOutput(); break;
132 case 'none':
133 $out = new noneStatsOutput(); break;
134 case 'text':
135 $out = new textStatsOutput(); break;
136 case 'wiki':
137 $out = new wikiStatsOutput(); break;
138 default:
139 usage(); wfDie();
140 break;
141 }
142
143 $langTool = new languages();
144
145 // Load message and compute stuff
146 $msgs = array();
147 foreach($langTool->getList() as $langcode) {
148 // Since they aren't loaded by default..
149 require_once( 'languages/Language' . $langcode . '.php' );
150 $arr = 'wgAllMessages'.$langcode;
151 if(@is_array($$arr)) {
152 $msgs[$wgContLang->lcfirst($langcode)] = array(
153 'total' => count($$arr),
154 'redundant' => redundant($$arr, $langcode),
155 );
156 } else {
157 $msgs[$wgContLang->lcfirst($langcode)] = array(
158 'total' => 0,
159 'redundant' => 0,
160 );
161 }
162 }
163
164 // Top entry
165 $out->heading();
166 $out->blockstart();
167 $out->element('Language', true);
168 $out->element('Translated', true);
169 $out->element('%', true);
170 $out->element('Untranslated', true);
171 $out->element('%', true);
172 $out->element('Redundant', true);
173 $out->element('%', true);
174 $out->blockend();
175
176 // Generate rows
177 foreach($msgs as $lang => $stats) {
178 $out->blockstart();
179 // Language
180 $out->element($wgContLang->getLanguageName(strtr($lang, '_', '-')) . " ($lang)");
181 // Translated
182 $out->element($stats['total'] . '/' . $msgs['en']['total']);
183 // % Translated
184 $out->element($out->formatPercent($stats['total'], $msgs['en']['total']));
185 // Untranslated
186 $out->element($msgs['en']['total'] - $stats['total']);
187 // % Untranslated
188 $out->element($out->formatPercent($msgs['en']['total'] - $stats['total'], $msgs['en']['total'], true));
189 // Redundant & % Redundant
190 if($stats['redundant'] =='NC') {
191 $out->element('NC');
192 $out->element('NC');
193 } else {
194 $out->element($stats['redundant'] . '/' . $stats['total']);
195 $out->element($out->formatPercent($stats['redundant'], $stats['total'],true));
196 }
197 $out->blockend();
198 }
199 $out->footer();
200
201 // Final output
202 echo $out->getContent();
203 ?>