Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
createCheckIndex.php
Go to the documentation of this file.
1<?php
12// Standard boilerplate to define $IP
13
17use MediaWiki\Languages\LanguageNameUtils;
18use MediaWiki\Maintenance\Maintenance;
19use MediaWiki\MediaWikiServices;
20use MediaWiki\Title\Title;
21
22if ( getenv( 'MW_INSTALL_PATH' ) !== false ) {
23 $IP = getenv( 'MW_INSTALL_PATH' );
24} else {
25 $dir = __DIR__;
26 $IP = "$dir/../../..";
27}
28require_once "$IP/maintenance/Maintenance.php";
29
30class CreateCheckIndex extends Maintenance {
31 public function __construct() {
32 parent::__construct();
33 $this->addDescription( 'Creates serialised database of messages that need ' .
34 'checking for problems.' );
35 $this->addOption(
36 'group',
37 'Comma separated list of group IDs to process (can use * as wildcard).',
38 true, /*required*/
39 true /*has arg*/
40 );
41
42 $this->addOption(
43 'verbose',
44 '(optional) Enable verbose logging. Default: off',
45 false, /*required*/
46 false /*has arg*/
47 );
48 $this->requireExtension( 'Translate' );
49 }
50
51 public function execute() {
52 $codes = MediaWikiServices::getInstance()
53 ->getLanguageNameUtils()
54 ->getLanguageNames( LanguageNameUtils::AUTONYMS, LanguageNameUtils::ALL );
55
56 // Exclude the documentation language code
57 global $wgTranslateDocumentationLanguageCode;
58 if ( $wgTranslateDocumentationLanguageCode ) {
59 unset( $codes[$wgTranslateDocumentationLanguageCode] );
60 }
61
62 $reqGroupsPattern = $this->getOption( 'group' );
63 $reqGroups = explode( ',', $reqGroupsPattern );
64 $reqGroups = array_map( 'trim', $reqGroups );
65 $reqGroups = MessageGroups::expandWildcards( $reqGroups );
66
67 $verbose = $this->hasOption( 'verbose' );
68
69 if ( !$reqGroups ) {
70 $this->fatalError( "Pattern '$reqGroupsPattern' did not match any groups" );
71 }
72
73 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
74
76 foreach ( $reqGroups as $id ) {
77 $g = MessageGroups::getGroup( $id );
78 // Aliases may have changed the id
79 $id = $g->getId();
80 $sourceLanguage = $g->getSourceLanguage();
81
82 $validator = $g->getValidator();
83 if ( !$validator ) {
84 unset( $g );
85 $this->output( "Skipping group $id due to lack of validators" );
86 continue;
87 }
88
89 // Initialise messages, using unique definitions if appropriate
90 // @phan-suppress-next-line PhanParamTooMany MessageGroupOld takes two args
91 $collection = $g->initCollection( $sourceLanguage, true );
92 if ( !count( $collection ) ) {
93 continue;
94 }
95
96 $this->output( "Processing group $id: ", $id );
97
98 // Skip source language code
99 $langCodes = $codes;
100 unset( $langCodes[$sourceLanguage] );
101
102 $langCodes = array_keys( $langCodes );
103 sort( $langCodes );
104
105 foreach ( $langCodes as $code ) {
106 $this->output( "$code ", $id );
107
108 $problematic = [];
109
110 $collection->resetForNewLanguage( $code );
111 $collection->loadTranslations();
112 $collection->filter( MessageCollection::FILTER_IGNORED, MessageCollection::EXCLUDE_MATCHING );
113 $collection->filter( MessageCollection::FILTER_FUZZY, MessageCollection::EXCLUDE_MATCHING );
114 $collection->filter( MessageCollection::FILTER_TRANSLATED, MessageCollection::INCLUDE_MATCHING );
115
116 foreach ( $collection as $key => $message ) {
117 $result = $validator->quickValidate( $message, $code );
118 if ( $result->hasIssues() ) {
119 if ( $verbose ) {
120 // Print it
121 $nsText = $contLang->getNsText( $g->getNamespace() );
122 $this->output( "# [[$nsText:$key/$code]]\n" );
123 }
124
125 // Add it to the array
126 $problematic[] = [ $g->getNamespace(), "$key/$code" ];
127 }
128 }
129
130 $this->tagFuzzy( $problematic );
131 }
132 }
133 }
134
135 public function tagFuzzy( array $problematic ): void {
136 if ( $problematic === [] ) {
137 return;
138 }
139
140 $titleConditions = [];
141 $dbw = $this->getDB( DB_PRIMARY );
142
143 foreach ( $problematic as $p ) {
144 // Normalize page key
145 $title = Title::makeTitleSafe( $p[0], $p[1] );
146 $titleText = $title->getDBkey();
147 $titleConditions[] = $dbw->makeList(
148 [
149 'page_namespace' => $p[0],
150 'page_title' => $titleText
151 ],
152 LIST_AND
153 );
154 }
155
156 $conds = $dbw->makeList( $titleConditions, LIST_OR );
157
158 $res = $dbw->newSelectQueryBuilder()
159 ->select( [ 'page_id', 'page_latest' ] )
160 ->from( 'page' )
161 ->where( $conds )
162 ->caller( __METHOD__ )
163 ->fetchResultSet();
164 if ( $res->numRows() === 0 ) {
165 return;
166 }
167 $inserts = [];
168 foreach ( $res as $row ) {
169 $inserts[] = [
170 'rt_page' => $row->page_id,
171 'rt_revision' => $row->page_latest,
172 'rt_type' => RevTagStore::FUZZY_TAG
173 ];
174 }
175 $dbw->newReplaceQueryBuilder()
176 ->replaceInto( 'revtag' )
177 ->uniqueIndexFields( [ 'rt_type', 'rt_page', 'rt_revision' ] )
178 ->rows( $inserts )
179 ->caller( __METHOD__ )
180 ->execute();
181 }
182}
183
184$maintClass = CreateCheckIndex::class;
185require_once RUN_MAINTENANCE_IF_MAIN;
Factory class for accessing message groups individually by id or all of them as a list.
Class to manage revision tags for translatable bundles.
This file contains the class for core message collections implementation.