Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
UpdateMessageBundleJob.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\MessageBundleTranslation;
5
6use Job;
8use MediaWiki\Logger\LoggerFactory;
9use MediaWiki\MediaWikiServices;
14use Title;
15
21class UpdateMessageBundleJob extends Job {
23 public function __construct( Title $title, $params = [] ) {
24 parent::__construct( 'UpdateMessageBundle', $title, $params );
25 }
26
27 public static function newJob( Title $bundlePageTitle, int $revisionId, ?int $previousRevisionId ): self {
28 return new self(
29 $bundlePageTitle,
30 [
31 'revisionId' => $revisionId,
32 'previousRevisionId' => $previousRevisionId,
33 ]
34 );
35 }
36
38 public function run(): void {
39 $mwInstance = MediaWikiServices::getInstance();
40 $lb = $mwInstance->getDBLoadBalancerFactory();
41 $jobQueue = $mwInstance->getJobQueueGroup();
42 $logger = LoggerFactory::getInstance( 'Translate.MessageBundle' );
43 $messageIndex = Services::getInstance()->getMessageIndex();
44
45 $logger->info( 'UpdateMessageBundleJob: Starting job for: ' . $this->getTitle()->getPrefixedText() );
46
47 // Not sure if this is necessary, but it should ensure that this job, which was created
48 // when a revision was saved, can read that revision from the replica. In addition, this
49 // may potentially do a bunch of more writes that could cause more replication lag.
50 if ( !$lb->waitForReplication() ) {
51 $logger->warning( 'UpdateMessageBundleJob: Continuing despite replication lag' );
52 }
53
54 // Setup
55 $bundlePageTitle = $this->getTitle();
56 $name = $bundlePageTitle->getPrefixedText();
57 $pageId = $bundlePageTitle->getId();
58 $groupId = MessageBundleMessageGroup::getGroupId( $name );
59 $params = $this->getParams();
60 // We don't care about the group description, so no need to pass it through
61 $group = new MessageBundleMessageGroup( $groupId, $name, $pageId, $params['revisionId'], null );
62 $messages = $group->getDefinitions();
63 $previousMessages = [];
64 if ( $params['previousRevisionId'] ) {
65 $groupPreviousVersion = new MessageBundleMessageGroup(
66 $groupId, $name, $pageId, $params['previousRevisionId'], null
67 );
68 $previousMessages = $groupPreviousVersion->getDefinitions();
69 }
70
71 // Fill in the front-cache. Ideally this should be done right away, but hopefully
72 // this is okay since we only trigger message group cache rebuild later in this job.
73 // It's possible that some other change triggers it earlier and makes the new group
74 // available before this step is complete.
75 $newKeys = array_diff( array_keys( $messages ), array_keys( $previousMessages ) );
76 $messageIndex->storeInterim( $group, $newKeys );
77
78 // Create jobs that will update the '/' source language pages. These pages should
79 // exist so that the editor can show differences for changed messages. Also compare
80 // against previous version (if any) to determine whether to mark translations as
81 // outdated. There is no support for renames.
82 $jobs = [];
83 $namespace = $group->getNamespace();
84 $code = $group->getSourceLanguage();
85 foreach ( $messages as $key => $value ) {
86 $title = Title::makeTitle( $namespace, "$key/$code" );
87 $previousValue = $previousMessages[$key] ?? null;
88 $fuzzy = $previousMessages !== null && $previousValue !== $value;
89 $jobs[] = MessageUpdateJob::newJob( $title, $value, $fuzzy );
90 }
91 $jobQueue->push( $jobs );
92 $logger->info(
93 'UpdateMessageBundleJob: Added {number} MessageUpdateJobs to the job queue for: {title}',
94 [
95 'number' => count( $jobs ),
96 'title' => $name
97 ]
98 );
99
100 // This is somewhat slow, so it has been postponed until now, but it's needed to
101 // make the group available for the message index rebuild.
102 MessageGroups::singleton()->recache();
103
104 $logger->info(
105 'UpdateMessageBundleJob: {title}: Recaching message groups',
106 [ 'title' => $name ]
107 );
108
109 // Schedule message index update. Thanks to front caching, it is okay if this takes
110 // a while (and on large wikis it does take a while!). Running it as a separate job
111 // also allows de-duplication.
113 $jobQueue->push( $job );
114 $logger->info(
115 'UpdateMessageBundleJob: {title}: Queue MessageIndexRebuildJob',
116 [ 'title' => $name ]
117 );
118
119 // Refresh or fill translations statistics. If this a new group, this prevents
120 // calculating the stats on the fly during read requests. If an existing group, this
121 // makes sure that the statistics are up-to-date.
123 $groupId,
125 );
126 }
127}
return[ 'Translate:ConfigHelper'=> static function():ConfigHelper { return new ConfigHelper();}, 'Translate:CsvTranslationImporter'=> static function(MediaWikiServices $services):CsvTranslationImporter { return new CsvTranslationImporter( $services->getWikiPageFactory());}, 'Translate:EntitySearch'=> static function(MediaWikiServices $services):EntitySearch { return new EntitySearch($services->getMainWANObjectCache(), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), MessageGroups::singleton(), $services->getNamespaceInfo(), $services->get( 'Translate:MessageIndex'), $services->getTitleParser(), $services->getTitleFormatter());}, 'Translate:ExternalMessageSourceStateImporter'=> static function(MediaWikiServices $services):ExternalMessageSourceStateImporter { return new ExternalMessageSourceStateImporter($services->getMainConfig(), $services->get( 'Translate:GroupSynchronizationCache'), $services->getJobQueueGroup(), LoggerFactory::getInstance( 'Translate.GroupSynchronization'), MessageIndex::singleton());}, 'Translate:GroupSynchronizationCache'=> static function(MediaWikiServices $services):GroupSynchronizationCache { return new GroupSynchronizationCache( $services->get( 'Translate:PersistentCache'));}, 'Translate:MessageBundleStore'=> static function(MediaWikiServices $services):MessageBundleStore { return new MessageBundleStore(new RevTagStore(), $services->getJobQueueGroup(), $services->getLanguageNameUtils(), $services->get( 'Translate:MessageIndex'));}, 'Translate:MessageGroupReview'=> static function(MediaWikiServices $services):MessageGroupReview { return new MessageGroupReview($services->getDBLoadBalancer(), $services->getHookContainer());}, 'Translate:MessageIndex'=> static function(MediaWikiServices $services):MessageIndex { $params=$services->getMainConfig() ->get( 'TranslateMessageIndex');if(is_string( $params)) { $params=(array) $params;} $class=array_shift( $params);return new $class( $params);}, 'Translate:ParsingPlaceholderFactory'=> static function():ParsingPlaceholderFactory { return new ParsingPlaceholderFactory();}, 'Translate:PersistentCache'=> static function(MediaWikiServices $services):PersistentCache { return new PersistentDatabaseCache($services->getDBLoadBalancer(), $services->getJsonCodec());}, 'Translate:ProgressStatsTableFactory'=> static function(MediaWikiServices $services):ProgressStatsTableFactory { return new ProgressStatsTableFactory($services->getLinkRenderer(), $services->get( 'Translate:ConfigHelper'));}, 'Translate:SubpageListBuilder'=> static function(MediaWikiServices $services):SubpageListBuilder { return new SubpageListBuilder($services->get( 'Translate:TranslatableBundleFactory'), $services->getLinkBatchFactory());}, 'Translate:TranslatableBundleFactory'=> static function(MediaWikiServices $services):TranslatableBundleFactory { return new TranslatableBundleFactory($services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:MessageBundleStore'));}, 'Translate:TranslatableBundleMover'=> static function(MediaWikiServices $services):TranslatableBundleMover { return new TranslatableBundleMover($services->getMovePageFactory(), $services->getJobQueueGroup(), $services->getLinkBatchFactory(), $services->get( 'Translate:TranslatableBundleFactory'), $services->get( 'Translate:SubpageListBuilder'), $services->getMainConfig() ->get( 'TranslatePageMoveLimit'));}, 'Translate:TranslatablePageParser'=> static function(MediaWikiServices $services):TranslatablePageParser { return new TranslatablePageParser($services->get( 'Translate:ParsingPlaceholderFactory'));}, 'Translate:TranslatablePageStore'=> static function(MediaWikiServices $services):TranslatablePageStore { return new TranslatablePageStore($services->get( 'Translate:MessageIndex'), $services->getJobQueueGroup(), new RevTagStore(), $services->getDBLoadBalancer());}, 'Translate:TranslationStashReader'=> static function(MediaWikiServices $services):TranslationStashReader { $db=$services->getDBLoadBalancer() ->getConnectionRef(DB_REPLICA);return new TranslationStashStorage( $db);}, 'Translate:TranslationStatsDataProvider'=> static function(MediaWikiServices $services):TranslationStatsDataProvider { return new TranslationStatsDataProvider(new ServiceOptions(TranslationStatsDataProvider::CONSTRUCTOR_OPTIONS, $services->getMainConfig()), $services->getObjectFactory());}, 'Translate:TranslationUnitStoreFactory'=> static function(MediaWikiServices $services):TranslationUnitStoreFactory { return new TranslationUnitStoreFactory( $services->getDBLoadBalancer());}, 'Translate:TranslatorActivity'=> static function(MediaWikiServices $services):TranslatorActivity { $query=new TranslatorActivityQuery($services->getMainConfig(), $services->getDBLoadBalancer());return new TranslatorActivity($services->getMainObjectStash(), $query, $services->getJobQueueGroup());}, 'Translate:TtmServerFactory'=> static function(MediaWikiServices $services):TtmServerFactory { $config=$services->getMainConfig();$default=$config->get( 'TranslateTranslationDefaultService');if( $default===false) { $default=null;} return new TtmServerFactory( $config->get( 'TranslateTranslationServices'), $default);}]
@phpcs-require-sorted-array
Minimal service container.
Definition Services.php:38
This class abstract MessageGroup statistics calculation and storing.
const FLAG_IMMEDIATE_WRITES
Do not defer updates. Meant for jobs like MessageGroupStatsRebuildJob.
const FLAG_NO_CACHE
Ignore cached values. Useful for updating stale values.
static forGroup( $id, $flags=0)
Returns stats for all languages in given group.
Factory class for accessing message groups individually by id or all of them as an list.
Job for rebuilding message index.
Job for updating translation pages when translation or message definition changes.
static newJob(Title $target, string $content, $fuzzy=false)
Create a normal message update job without a rename process.