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