49 public const DISPLAY_TITLE_UNIT_ID =
'Page display title';
51 protected PageIdentity $title;
60 protected $pageDisplayTitle;
62 private $targetLanguage;
64 protected function __construct( PageIdentity $title ) {
65 $this->title = $title;
66 $this->revTagStore = Services::getInstance()->getRevTagStore();
74 public static function newFromText( Title $title,
string $text ): self {
75 $obj = new self( $title );
77 $obj->source =
'text';
87 public static function newFromRevision( PageIdentity $title,
int $revision ): self {
88 $rev = MediaWikiServices::getInstance()
90 ->getRevisionByTitle( $title, $revision );
91 if ( $rev ===
null ) {
92 throw new RuntimeException(
'Revision is null' );
95 $obj =
new self( $title );
96 $obj->source =
'revision';
97 $obj->revision = $revision;
107 $obj = new self( $title );
108 $obj->source =
'title';
115 return Title::newFromPageIdentity( $this->title );
118 public function getPageIdentity(): PageIdentity {
124 if ( $this->text !== null ) {
128 if ( $this->source ===
'title' ) {
129 $revision = $this->getMarkedTag();
130 if ( !is_int( $revision ) ) {
131 throw new LogicException(
132 "Trying to load a text for {$this->getPageIdentity()} which is not marked for translation"
135 $this->revision = $revision;
138 $flags = Utilities::shouldReadFromPrimary()
139 ? IDBAccessObject::READ_LATEST
140 : IDBAccessObject::READ_NORMAL;
141 $rev = MediaWikiServices::getInstance()
142 ->getRevisionLookup()
143 ->getRevisionByTitle( $this->getPageIdentity(), $this->revision, $flags );
144 $content = $rev->getContent( SlotRecord::MAIN );
145 $text = ( $content instanceof TextContent ) ? $content->getText() :
null;
147 if ( !is_string( $text ) ) {
148 throw new RuntimeException(
"Failed to load text for {$this->getPageIdentity()}" );
170 return $this->getTitle()->getPageLanguage()->getCode();
175 return self::getMessageGroupIdFromTitle( $this->getPageIdentity() );
180 return 'page-' . MediaWikiServices::getInstance()->getTitleFormatter()->getPrefixedText( $page );
188 $groupId = $this->getMessageGroupId();
189 $group = MessageGroups::getGroup( $groupId );
194 throw new RuntimeException(
195 "Expected $groupId to be of type WikiPageMessageGroup; got " .
203 if ( $this->pageDisplayTitle !== null ) {
204 return $this->pageDisplayTitle;
208 $factory = Services::getInstance()->getTranslationUnitStoreFactory();
209 $store = $factory->getReader( $this->getPageIdentity() );
210 $this->pageDisplayTitle = in_array( self::DISPLAY_TITLE_UNIT_ID, $store->getNames() );
212 return $this->pageDisplayTitle;
218 if ( !$this->hasPageDisplayTitle() ) {
223 $section = str_replace(
' ',
'_', self::DISPLAY_TITLE_UNIT_ID );
224 $page = MediaWikiServices::getInstance()->getTitleFormatter()->getPrefixedDBkey( $this->getPageIdentity() );
227 $group = $this->getMessageGroup();
228 }
catch ( RuntimeException ) {
237 return $group->getMessage(
"$page/$section", $languageCode, IDBAccessObject::READ_NORMAL );
240 public function getStrippedSourcePageText(): string {
241 $parser = Services::getInstance()->getTranslatablePageParser();
242 $text = $parser->cleanupTags( $this->getText() );
243 $text = preg_replace(
'~<languages\s*/>\n?~s',
'', $text );
248 public static function getTranslationPageFromTitle( Title $title ): ?TranslationPage {
249 $self = self::isTranslationPage( $title );
250 return $self ? $self->getTranslationPage( $self->targetLanguage ) :
null;
253 public function getTranslationPage(
string $targetLanguage ): TranslationPage {
254 $mwServices = MediaWikiServices::getInstance();
255 $config = $mwServices->getMainConfig();
256 $services = Services::getInstance();
257 $parser = $services->getTranslatablePageParser();
258 $parserOutput = $parser->parse( $this->getText() );
259 $pageVersion = (int)$services->getMessageGroupMetadata()
260 ->get( $this->getMessageGroupId(),
'version' );
261 $wrapUntranslated = $pageVersion >= 2;
262 $languageFactory = $mwServices->getLanguageFactory();
264 return new TranslationPage(
266 $this->getMessageGroup(),
267 $languageFactory->getLanguage( $targetLanguage ),
268 $languageFactory->getLanguage( $this->getSourceLanguageCode() ),
269 $config->get(
'TranslateKeepOutdatedTranslations' ),
277 $this->revTagStore->replaceTag( $this->getPageIdentity(), RevTagStore::TP_MARK_TAG, $revision, $value );
278 self::clearSourcePageCache();
283 $this->revTagStore->replaceTag( $this->getPageIdentity(),
RevTagStore::TP_READY_TAG, $revision );
284 if ( !self::isSourcePage( $this->getPageIdentity() ) ) {
285 self::clearSourcePageCache();
291 return $this->revTagStore->getLatestRevisionWithTag( $this->getPageIdentity(),
RevTagStore::TP_MARK_TAG );
296 return $this->revTagStore->getLatestRevisionWithTag( $this->getPageIdentity(),
RevTagStore::TP_READY_TAG );
306 'group' => $this->getMessageGroupId(),
312 $translate = SpecialPage::getTitleFor(
'Translate' );
314 return $translate->getLocalURL( $params );
319 $mwServices = MediaWikiServices::getInstance();
321 $messageGroup = $this->getMessageGroup();
322 $knownLanguageCodes = $messageGroup ? $messageGroup->getTranslatableLanguages() :
null;
323 $knownLanguageCodes ??= Utilities::getLanguageNames( LanguageNameUtils::AUTONYMS );
325 $prefixedDbTitleKey = $this->getPageIdentity()->getDBkey() .
'/';
326 $baseNamespace = $this->getPageIdentity()->getNamespace();
329 $linkBatch = $mwServices->getLinkBatchFactory()->newLinkBatch();
330 foreach ( array_keys( $knownLanguageCodes ) as $code ) {
331 $linkBatch->add( $baseNamespace, $prefixedDbTitleKey . $code );
334 $translationPages = [];
335 foreach ( $linkBatch->getPageIdentities() as $pageIdentity ) {
336 if ( $pageIdentity->exists() ) {
337 $translationPages[] = Title::newFromPageIdentity( $pageIdentity );
341 return $translationPages;
346 return $this->getTranslationUnitPagesByTitle( $this->title, $code );
349 public function getTranslationPercentages(): array {
352 $group = $this->getMessageGroup();
353 }
catch ( RuntimeException ) {
361 $titles = $this->getTranslationPages();
362 $temp = MessageGroupStats::forGroup( $this->getMessageGroupId(), MessageGroupStats::FLAG_CACHE_ONLY );
365 foreach ( $titles as $t ) {
366 $handle =
new MessageHandle( $t );
367 $code = $handle->getCode();
371 $stats[$code] = 0.00;
372 if ( ( $temp[$code][MessageGroupStats::TOTAL] ?? 0 ) > 0 ) {
373 $total = $temp[$code][MessageGroupStats::TOTAL];
374 $translated = $temp[$code][MessageGroupStats::TRANSLATED];
375 $percentage = $translated / $total;
376 $stats[$code] = sprintf(
'%.2f', $percentage );
381 $stats[$this->getSourceLanguageCode()] = 1.00;
386 public function supportsTransclusion(): ?bool {
387 $transclusion = Services::getInstance()
388 ->getMessageGroupMetadata()
389 ->get( $this->getMessageGroupId(),
'transclusion' );
390 if ( $transclusion ===
false ) {
394 return $transclusion ===
'1';
397 public function getRevisionRecordWithFallback(): ?RevisionRecord {
398 $title = $this->getTitle();
399 $store = MediaWikiServices::getInstance()->getRevisionStore();
400 $revRecord = $store->getRevisionByTitle( $title->getSubpage( $this->targetLanguage ) );
406 return $store->getRevisionByTitle( $title->getSubpage( $this->getSourceLanguageCode() ) );
411 return $this->getMarkedTag() !== null;
416 return $this->getMarkedTag() !== null;
422 if ( !Utilities::isTranslationPage( $handle ) ) {
426 $languageCode = $handle->getCode();
427 $newTitle = $handle->getTitleForBase();
429 $page = self::newFromTitle( $newTitle );
431 if ( $page->getMarkedTag() ===
null ) {
435 $page->targetLanguage = $languageCode;
444 $parts = explode(
'/', $translationUnit->getText() );
447 $language = array_pop( $parts );
448 $section = array_pop( $parts );
449 $sourcepage = implode(
'/', $parts );
452 'sourcepage' => $sourcepage,
453 'section' => $section,
454 'language' => $language
458 public static function isSourcePage( PageIdentity $page ): bool {
459 if ( !$page->exists() ) {
467 $localCache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
468 $localKey = $localCache->makeKey(
'pagetranslation',
'sourcepages',
'local' );
471 $translatablePageIds = $localCache->getWithSetCallback(
473 $localCache::TTL_SECOND * 8,
475 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
476 $cacheKey = $cache->makeKey(
'pagetranslation',
'sourcepages' );
478 return $cache->getWithSetCallback(
480 $cache::TTL_HOUR * 2,
481 [ TranslatablePage::class,
'getCacheValue' ],
483 'checkKeys' => [ $cacheKey ],
484 'pcTTL' => $cache::TTL_PROC_SHORT,
485 'pcGroup' => __CLASS__ .
':1',
490 $localCache::READ_LATEST
493 return str_contains( $translatablePageIds, (
',' . $page->getId() .
',' ) );
498 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
499 $cache->touchCheckKey( $cache->makeKey(
'pagetranslation',
'sourcepages' ) );
502 public static function determineStatus(
503 ?
int $readyRevisionId,
504 ?
int $markRevisionId,
505 int $latestRevisionId
508 if ( $markRevisionId ===
null ) {
510 if ( $readyRevisionId === $latestRevisionId ) {
511 $status = TranslatablePageStatus::PROPOSED;
516 } elseif ( $readyRevisionId === $latestRevisionId ) {
517 if ( $markRevisionId === $readyRevisionId ) {
519 $status = TranslatablePageStatus::ACTIVE;
521 $status = TranslatablePageStatus::OUTDATED;
525 $status = TranslatablePageStatus::BROKEN;
528 return new TranslatablePageStatus( $status );
539 public static function getCacheValue( $oldValue, &$ttl, array &$setOpts ): string {
540 $dbr = MediaWikiServices::getInstance()->getConnectionProvider()->getReplicaDatabase();
541 $setOpts += Database::getCacheSetOptions( $dbr );
543 $ids = RevTagStore::getTranslatableBundleIds(
544 RevTagStore::TP_MARK_TAG,
545 RevTagStore::TP_READY_TAG
550 return ',' . implode(
',', $ids ) .
',';
return[ 'Translate:AggregateGroupManager'=> static function(MediaWikiServices $services):AggregateGroupManager { return new AggregateGroupManager($services->getTitleFactory(), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:AggregateGroupMessageGroupFactory'=> static function(MediaWikiServices $services):AggregateGroupMessageGroupFactory { return new AggregateGroupMessageGroupFactory($services->get( 'Translate:MessageGroupMetadata'));}, '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:ExternalMessageSourceStateComparator'=> static function(MediaWikiServices $services):ExternalMessageSourceStateComparator { return new ExternalMessageSourceStateComparator(new SimpleStringComparator(), $services->getRevisionLookup(), $services->getPageStore());}, 'Translate:ExternalMessageSourceStateImporter'=> static function(MediaWikiServices $services):ExternalMessageSourceStateImporter { return new ExternalMessageSourceStateImporter($services->get( 'Translate:GroupSynchronizationCache'), $services->getJobQueueGroup(), LoggerFactory::getInstance(LogNames::GROUP_SYNCHRONIZATION), $services->get( 'Translate:MessageIndex'), $services->getTitleFactory(), $services->get( 'Translate:MessageGroupSubscription'), new ServiceOptions(ExternalMessageSourceStateImporter::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:FileBasedMessageGroupFactory'=> static function(MediaWikiServices $services):FileBasedMessageGroupFactory { return new FileBasedMessageGroupFactory(new MessageGroupConfigurationParser(), $services->getContentLanguageCode() ->toString(), new ServiceOptions(FileBasedMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:FileFormatFactory'=> static function(MediaWikiServices $services):FileFormatFactory { return new FileFormatFactory( $services->getObjectFactory());}, 'Translate:GroupSynchronizationCache'=> static function(MediaWikiServices $services):GroupSynchronizationCache { return new GroupSynchronizationCache( $services->get( 'Translate:PersistentCache'));}, 'Translate:HookDefinedMessageGroupFactory'=> static function(MediaWikiServices $services):HookDefinedMessageGroupFactory { return new HookDefinedMessageGroupFactory( $services->get( 'Translate:HookRunner'));}, 'Translate:HookRunner'=> static function(MediaWikiServices $services):HookRunner { return new HookRunner( $services->getHookContainer());}, 'Translate:MessageBundleDependencyPurger'=> static function(MediaWikiServices $services):MessageBundleDependencyPurger { return new MessageBundleDependencyPurger( $services->get( 'Translate:TranslatableBundleFactory'));}, 'Translate:MessageBundleMessageGroupFactory'=> static function(MediaWikiServices $services):MessageBundleMessageGroupFactory { return new MessageBundleMessageGroupFactory($services->get( 'Translate:MessageGroupMetadata'), new ServiceOptions(MessageBundleMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:MessageBundleStore'=> static function(MediaWikiServices $services):MessageBundleStore { return new MessageBundleStore($services->get( 'Translate:RevTagStore'), $services->getJobQueueGroup(), $services->getLanguageNameUtils(), $services->get( 'Translate:MessageIndex'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:MessageBundleTranslationLoader'=> static function(MediaWikiServices $services):MessageBundleTranslationLoader { return new MessageBundleTranslationLoader( $services->getLanguageFallback());}, 'Translate:MessageGroupMetadata'=> static function(MediaWikiServices $services):MessageGroupMetadata { return new MessageGroupMetadata( $services->getConnectionProvider());}, 'Translate:MessageGroupReviewStore'=> static function(MediaWikiServices $services):MessageGroupReviewStore { return new MessageGroupReviewStore($services->getConnectionProvider(), $services->get( 'Translate:HookRunner'));}, 'Translate:MessageGroupStatsTableFactory'=> static function(MediaWikiServices $services):MessageGroupStatsTableFactory { return new MessageGroupStatsTableFactory($services->get( 'Translate:ProgressStatsTableFactory'), $services->getLinkRenderer(), $services->get( 'Translate:MessageGroupReviewStore'), $services->get( 'Translate:MessageGroupMetadata'), $services->getMainConfig() ->get( 'TranslateWorkflowStates') !==false);}, 'Translate:MessageGroupSubscription'=> static function(MediaWikiServices $services):MessageGroupSubscription { return new MessageGroupSubscription($services->get( 'Translate:MessageGroupSubscriptionStore'), $services->getJobQueueGroup(), $services->getUserIdentityLookup(), LoggerFactory::getInstance(LogNames::GROUP_SUBSCRIPTION), new ServiceOptions(MessageGroupSubscription::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:MessageGroupSubscriptionHookHandler'=> static function(MediaWikiServices $services):?MessageGroupSubscriptionHookHandler { if(! $services->getExtensionRegistry() ->isLoaded( 'Echo')) { return null;} return new MessageGroupSubscriptionHookHandler($services->get( 'Translate:MessageGroupSubscription'), $services->getUserFactory());}, 'Translate:MessageGroupSubscriptionStore'=> static function(MediaWikiServices $services):MessageGroupSubscriptionStore { return new MessageGroupSubscriptionStore( $services->getConnectionProvider());}, 'Translate:MessageIndex'=> static function(MediaWikiServices $services):MessageIndex { $params=(array) $services->getMainConfig() ->get( 'TranslateMessageIndex');$class=array_shift( $params);$implementationMap=['HashMessageIndex'=> HashMessageIndex::class, 'CDBMessageIndex'=> CDBMessageIndex::class, 'DatabaseMessageIndex'=> DatabaseMessageIndex::class, 'hash'=> HashMessageIndex::class, 'cdb'=> CDBMessageIndex::class, 'database'=> DatabaseMessageIndex::class,];$messageIndexStoreClass=$implementationMap[$class] ?? $implementationMap['database'];return new MessageIndex(new $messageIndexStoreClass, $services->getMainWANObjectCache(), $services->getJobQueueGroup(), $services->get( 'Translate:HookRunner'), LoggerFactory::getInstance(LogNames::MAIN), $services->getMainObjectStash(), $services->getConnectionProvider(), new ServiceOptions(MessageIndex::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:MessagePrefixStats'=> static function(MediaWikiServices $services):MessagePrefixStats { return new MessagePrefixStats( $services->getTitleParser());}, 'Translate:ParsingPlaceholderFactory'=> static function():ParsingPlaceholderFactory { return new ParsingPlaceholderFactory();}, 'Translate:PersistentCache'=> static function(MediaWikiServices $services):PersistentCache { return new PersistentDatabaseCache($services->getConnectionProvider(), $services->getJsonCodec());}, 'Translate:ProgressStatsTableFactory'=> static function(MediaWikiServices $services):ProgressStatsTableFactory { return new ProgressStatsTableFactory($services->getLinkRenderer(), $services->get( 'Translate:ConfigHelper'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:RevTagStore'=> static function(MediaWikiServices $services):RevTagStore { return new RevTagStore( $services->getConnectionProvider());}, 'Translate:SubpageListBuilder'=> static function(MediaWikiServices $services):SubpageListBuilder { return new SubpageListBuilder($services->get( 'Translate:TranslatableBundleFactory'), $services->getLinkBatchFactory());}, 'Translate:TranslatableBundleDeleter'=> static function(MediaWikiServices $services):TranslatableBundleDeleter { return new TranslatableBundleDeleter($services->getMainObjectStash(), $services->getJobQueueGroup(), $services->get( 'Translate:SubpageListBuilder'), $services->get( 'Translate:TranslatableBundleFactory'));}, 'Translate:TranslatableBundleExporter'=> static function(MediaWikiServices $services):TranslatableBundleExporter { return new TranslatableBundleExporter($services->get( 'Translate:SubpageListBuilder'), $services->getWikiExporterFactory(), $services->getConnectionProvider());}, 'Translate:TranslatableBundleFactory'=> static function(MediaWikiServices $services):TranslatableBundleFactory { return new TranslatableBundleFactory($services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:MessageBundleStore'));}, 'Translate:TranslatableBundleImporter'=> static function(MediaWikiServices $services):TranslatableBundleImporter { return new TranslatableBundleImporter($services->getWikiImporterFactory(), $services->get( 'Translate:TranslatablePageParser'), $services->getRevisionLookup(), $services->getNamespaceInfo(), $services->getTitleFactory(), $services->getFormatterFactory());}, '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->getConnectionProvider(), $services->getObjectCacheFactory(), $services->getMainConfig() ->get( 'TranslatePageMoveLimit'));}, 'Translate:TranslatableBundleStatusStore'=> static function(MediaWikiServices $services):TranslatableBundleStatusStore { return new TranslatableBundleStatusStore($services->getConnectionProvider() ->getPrimaryDatabase(), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), $services->getDBLoadBalancer() ->getMaintenanceConnectionRef(DB_PRIMARY));}, 'Translate:TranslatablePageMarker'=> static function(MediaWikiServices $services):TranslatablePageMarker { return new TranslatablePageMarker($services->getConnectionProvider(), $services->getJobQueueGroup(), $services->getLinkRenderer(), MessageGroups::singleton(), $services->get( 'Translate:MessageIndex'), $services->getTitleFormatter(), $services->getTitleParser(), $services->get( 'Translate:TranslatablePageParser'), $services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:TranslatablePageStateStore'), $services->get( 'Translate:TranslationUnitStoreFactory'), $services->get( 'Translate:MessageGroupMetadata'), $services->getWikiPageFactory(), $services->get( 'Translate:TranslatablePageView'), $services->get( 'Translate:MessageGroupSubscription'), $services->getFormatterFactory(), $services->get( 'Translate:HookRunner'),);}, 'Translate:TranslatablePageMessageGroupFactory'=> static function(MediaWikiServices $services):TranslatablePageMessageGroupFactory { return new TranslatablePageMessageGroupFactory(new ServiceOptions(TranslatablePageMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:TranslatablePageParser'=> static function(MediaWikiServices $services):TranslatablePageParser { return new TranslatablePageParser($services->get( 'Translate:ParsingPlaceholderFactory'));}, 'Translate:TranslatablePageStateStore'=> static function(MediaWikiServices $services):TranslatablePageStateStore { return new TranslatablePageStateStore($services->get( 'Translate:PersistentCache'), $services->getPageStore());}, 'Translate:TranslatablePageStore'=> static function(MediaWikiServices $services):TranslatablePageStore { return new TranslatablePageStore($services->get( 'Translate:MessageIndex'), $services->getJobQueueGroup(), $services->get( 'Translate:RevTagStore'), $services->getConnectionProvider(), $services->get( 'Translate:TranslatableBundleStatusStore'), $services->get( 'Translate:TranslatablePageParser'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:TranslatablePageView'=> static function(MediaWikiServices $services):TranslatablePageView { return new TranslatablePageView($services->getConnectionProvider(), $services->get( 'Translate:TranslatablePageStateStore'), new ServiceOptions(TranslatablePageView::SERVICE_OPTIONS, $services->getMainConfig()));}, 'Translate:TranslateSandbox'=> static function(MediaWikiServices $services):TranslateSandbox { return new TranslateSandbox($services->getUserFactory(), $services->getConnectionProvider(), $services->getPermissionManager(), $services->getAuthManager(), $services->getUserGroupManager(), $services->getActorStore(), $services->getUserOptionsManager(), $services->getJobQueueGroup(), $services->get( 'Translate:HookRunner'), new ServiceOptions(TranslateSandbox::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:TranslationStashReader'=> static function(MediaWikiServices $services):TranslationStashReader { return new TranslationStashStorage( $services->getConnectionProvider() ->getPrimaryDatabase());}, 'Translate:TranslationStatsDataProvider'=> static function(MediaWikiServices $services):TranslationStatsDataProvider { return new TranslationStatsDataProvider(new ServiceOptions(TranslationStatsDataProvider::CONSTRUCTOR_OPTIONS, $services->getMainConfig()), $services->getObjectFactory(), $services->getConnectionProvider());}, '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);}, 'Translate:WorkflowStatesMessageGroupLoader'=> static function(MediaWikiServices $services):WorkflowStatesMessageGroupLoader { return new WorkflowStatesMessageGroupLoader(new ServiceOptions(WorkflowStatesMessageGroupLoader::CONSTRUCTOR_OPTIONS, $services->getMainConfig()),);},]
@phpcs-require-sorted-array