Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
MessageGroupStatsTable.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\Statistics;
5
6use Html;
7use Language;
9use MediaWiki\Linker\LinkRenderer;
10use MessageGroup;
12use MessageLocalizer;
13use SpecialPage;
14use Title;
16use Wikimedia\Rdbms\ILoadBalancer;
17
25 private ILoadBalancer $loadBalancer;
26 private LinkRenderer $linkRenderer;
27 private MessageLocalizer $localizer;
28 private Language $interfaceLanguage;
29 private StatsTable $table;
31 private bool $incompleteStats;
32 private array $languageNames;
33 private Title $translateTitle;
35 private array $states;
36 private bool $haveTranslateWorkflowStates;
37
38 public function __construct(
39 StatsTable $table,
40 ILoadBalancer $loadBalancer,
41 LinkRenderer $linkRenderer,
42 MessageLocalizer $localizer,
43 Language $interfaceLanguage,
44 bool $haveTranslateWorkflowStates
45 ) {
46 $this->table = $table;
47 $this->loadBalancer = $loadBalancer;
48 $this->linkRenderer = $linkRenderer;
49 $this->incompleteStats = false;
50 $this->localizer = $localizer;
51 $this->interfaceLanguage = $interfaceLanguage;
52 $this->haveTranslateWorkflowStates = $haveTranslateWorkflowStates;
53 $this->languageNames = Utilities::getLanguageNames( $this->interfaceLanguage->getCode() );
54 $this->translateTitle = SpecialPage::getTitleFor( 'Translate' );
55 }
56
57 public function get(
58 array $stats,
59 MessageGroup $group,
60 bool $noComplete,
61 bool $noEmpty
62 ): ?string {
63 $out = '';
64 $rowCount = 0;
65 $totals = MessageGroupStats::getEmptyStats();
66 $groupId = $group->getId();
67
68 $languages = array_keys(
69 Utilities::getLanguageNames( $this->interfaceLanguage->getCode() )
70 );
71 sort( $languages );
72 $this->filterPriorityLangs( $languages, $groupId, $stats );
73
74 // If workflow states are configured, adds a workflow states column
75 if ( $this->haveTranslateWorkflowStates ) {
76 $this->table->addExtraColumn( $this->localizer->msg( 'translate-stats-workflow' ) );
77 }
78
79 foreach ( $languages as $code ) {
80 if ( $this->table->isExcluded( $group, $code ) ) {
81 continue;
82 }
83
84 $languageStats = $stats[$code];
85 $row = $this->makeRow(
86 $this->table,
87 $code,
88 $languageStats,
89 $group,
90 $rowCount,
91 $noComplete,
92 $noEmpty
93 );
94 if ( $row ) {
95 $rowCount += 1;
96 $out .= $row;
97 $totals = MessageGroupStats::multiAdd( $totals, $languageStats );
98 }
99 }
100
101 if ( $out ) {
102 $this->table->setMainColumnHeader( $this->localizer->msg( 'translate-mgs-column-language' ) );
103 $out = $this->table->createHeader() . "\n" . $out;
104 $out .= Html::closeElement( 'tbody' );
105
106 $out .= Html::openElement( 'tfoot' );
107 $out .= $this->table->makeTotalRow(
108 $this->localizer->msg( 'translate-mgs-totals' )->numParams( $rowCount ),
109 $totals
110 );
111 $out .= Html::closeElement( 'tfoot' );
112
113 $out .= Html::closeElement( 'table' );
114
115 return $out;
116 } else {
117 return null;
118 }
119 }
120
121 public function areStatsIncomplete(): bool {
122 return $this->incompleteStats;
123 }
124
125 private function getWorkflowStates( string $groupId ): array {
126 $db = $this->loadBalancer->getConnection( DB_REPLICA );
127 $res = $db->select(
128 'translate_groupreviews',
129 [ 'tgr_state', 'tgr_lang' ],
130 [ 'tgr_group' => $groupId ],
131 __METHOD__
132 );
133
134 $states = [];
135 foreach ( $res as $row ) {
136 $states[$row->tgr_lang] = $row->tgr_state;
137 }
138
139 return $states;
140 }
141
142 private function makeRow(
143 StatsTable $table,
144 string $languageCode,
145 array $stats,
146 MessageGroup $group,
147 int $rowCount,
148 bool $noComplete,
149 bool $noEmpty
150 ): ?string {
151 $total = $stats[MessageGroupStats::TOTAL];
152 $translated = $stats[MessageGroupStats::TRANSLATED];
153 $fuzzy = $stats[MessageGroupStats::FUZZY];
154 $extra = [];
155
156 if ( $total === null ) {
157 $this->incompleteStats = true;
158 } else {
159 if ( $noComplete && $fuzzy === 0 && $translated === $total ) {
160 return null;
161 }
162
163 if ( $noEmpty && $translated === 0 && $fuzzy === 0 ) {
164 return null;
165 }
166
167 // Skip below 2% if "don't show without translations" is checked.
168 if ( $noEmpty && ( $translated / $total ) < 0.02 ) {
169 return null;
170 }
171
172 if ( $translated === $total ) {
173 $extra = [ 'action' => 'proofread' ];
174 }
175 }
176
177 $rowParams = [];
178 if ( $rowCount % 2 === 0 ) {
179 $rowParams[ 'class' ] = 'tux-statstable-even';
180 }
181
182 $out = "\t" . Html::openElement( 'tr', $rowParams );
183 $out .= "\n\t\t" . $this->getMainColumnCell( $languageCode, $extra, $group->getId() );
184 $out .= $table->makeNumberColumns( $stats );
185 $out .= $this->getWorkflowStateCell( $table, $languageCode, $group );
186
187 $out .= "\n\t" . Html::closeElement( 'tr' ) . "\n";
188
189 return $out;
190 }
191
192 private function getMainColumnCell( string $code, array $params, string $groupId ): string {
193 if ( isset( $this->languageNames[$code] ) ) {
194 $text = "$code: {$this->languageNames[$code]}";
195 } else {
196 $text = $code;
197 }
198
199 // Do not render links when generating table for MessagePrefixMessageGroup
200 // as this is a dynamic group whose contents are based on user input
201 if ( $groupId === '!prefix' ) {
202 return Html::rawElement( 'td', [], $text );
203 }
204
205 $queryParameters = $params + [
206 'group' => $groupId,
207 'language' => $code
208 ];
209
210 $link = $this->linkRenderer->makeKnownLink(
211 $this->translateTitle,
212 $text,
213 [],
214 $queryParameters
215 );
216
217 return Html::rawElement( 'td', [], $link );
218 }
219
221 private function getWorkflowStateCell( StatsTable $table, string $language, MessageGroup $group ): string {
222 if ( !$this->haveTranslateWorkflowStates ) {
223 return '';
224 }
225
226 $this->states ??= $this->getWorkflowStates( $group->getId() );
227 return $table->makeWorkflowStateCell( $this->states[$language] ?? null, $group, $language );
228 }
229
235 private function filterPriorityLangs( array &$languages, string $group, array $cache ): void {
236 $filterLangs = TranslateMetadata::get( $group, 'prioritylangs' );
237 if ( $filterLangs === false || strlen( $filterLangs ) === 0 ) {
238 // No restrictions, keep everything
239 return;
240 }
241 $filter = array_flip( explode( ',', $filterLangs ) );
242 foreach ( $languages as $id => $code ) {
243 if ( isset( $filter[$code] ) ) {
244 continue;
245 }
246 $translated = $cache[$code][1];
247 if ( $translated === 0 ) {
248 unset( $languages[$id] );
249 }
250 }
251 }
252}
Used to build the table displayed on Special:MessageGroupStats.
Implements generation of HTML stats table.
makeNumberColumns(array $stats)
Makes partial row from completion numbers.
Essentially random collection of helper functions, similar to GlobalFunctions.php.
Definition Utilities.php:30
This class abstract MessageGroup statistics calculation and storing.
Interface for message groups.