31 public function __construct() {
32 parent::__construct();
33 $this->addDescription(
'Creates serialised database of messages that need ' .
34 'checking for problems.' );
37 'Comma separated list of group IDs to process (can use * as wildcard).',
44 '(optional) Enable verbose logging. Default: off',
48 $this->requireExtension(
'Translate' );
51 public function execute() {
52 $codes = MediaWikiServices::getInstance()
53 ->getLanguageNameUtils()
54 ->getLanguageNames( LanguageNameUtils::AUTONYMS, LanguageNameUtils::ALL );
57 global $wgTranslateDocumentationLanguageCode;
58 if ( $wgTranslateDocumentationLanguageCode ) {
59 unset( $codes[$wgTranslateDocumentationLanguageCode] );
62 $reqGroupsPattern = $this->getOption(
'group' );
63 $reqGroups = explode(
',', $reqGroupsPattern );
64 $reqGroups = array_map(
'trim', $reqGroups );
65 $reqGroups = MessageGroups::expandWildcards( $reqGroups );
67 $verbose = $this->hasOption(
'verbose' );
70 $this->fatalError(
"Pattern '$reqGroupsPattern' did not match any groups" );
73 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
76 foreach ( $reqGroups as $id ) {
77 $g = MessageGroups::getGroup( $id );
80 $sourceLanguage = $g->getSourceLanguage();
82 $validator = $g->getValidator();
85 $this->output(
"Skipping group $id due to lack of validators" );
91 $collection = $g->initCollection( $sourceLanguage,
true );
92 if ( !count( $collection ) ) {
96 $this->output(
"Processing group $id: ", $id );
100 unset( $langCodes[$sourceLanguage] );
102 $langCodes = array_keys( $langCodes );
105 foreach ( $langCodes as $code ) {
106 $this->output(
"$code ", $id );
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 );
116 foreach ( $collection as $key => $message ) {
117 $result = $validator->quickValidate( $message, $code );
118 if ( $result->hasIssues() ) {
121 $nsText = $contLang->getNsText( $g->getNamespace() );
122 $this->output(
"# [[$nsText:$key/$code]]\n" );
126 $problematic[] = [ $g->getNamespace(),
"$key/$code" ];
130 $this->tagFuzzy( $problematic );
135 public function tagFuzzy( array $problematic ):
void {
136 if ( $problematic === [] ) {
140 $titleConditions = [];
141 $dbw = $this->getDB( DB_PRIMARY );
143 foreach ( $problematic as $p ) {
145 $title = Title::makeTitleSafe( $p[0], $p[1] );
146 $titleText = $title->getDBkey();
147 $titleConditions[] = $dbw->makeList(
149 'page_namespace' => $p[0],
150 'page_title' => $titleText
156 $conds = $dbw->makeList( $titleConditions, LIST_OR );
158 $res = $dbw->newSelectQueryBuilder()
159 ->select( [
'page_id',
'page_latest' ] )
162 ->caller( __METHOD__ )
164 if ( $res->numRows() === 0 ) {
168 foreach ( $res as $row ) {
170 'rt_page' => $row->page_id,
171 'rt_revision' => $row->page_latest,
172 'rt_type' => RevTagStore::FUZZY_TAG
175 $dbw->newReplaceQueryBuilder()
176 ->replaceInto(
'revtag' )
177 ->uniqueIndexFields( [
'rt_type',
'rt_page',
'rt_revision' ] )
179 ->caller( __METHOD__ )