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