Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
Utilities.php
1<?php
2declare( strict_types = 1 );
3
5
6use MediaWiki\Config\ConfigException;
7use MediaWiki\Content\Content;
8use MediaWiki\Content\TextContent;
9use MediaWiki\Context\RequestContext;
14use MediaWiki\Html\Html;
15use MediaWiki\Language\LanguageCode;
16use MediaWiki\Language\LanguageNameUtils;
17use MediaWiki\MediaWikiServices;
18use MediaWiki\Revision\RevisionRecord;
19use MediaWiki\Revision\SlotRecord;
20use MediaWiki\Title\Title;
21use MessageGroup;
22use UnexpectedValueException;
23use Wikimedia\Rdbms\IReadableDatabase;
24
30class Utilities {
39 public static function title( string $message, string $code, int $ns = NS_MEDIAWIKI ): string {
40 // Cache some amount of titles for speed.
41 static $cache = [];
42 $key = $ns . ':' . $message;
43
44 if ( !isset( $cache[$key] ) ) {
45 $cache[$key] = Title::capitalize( $message, $ns );
46 }
47
48 if ( $code ) {
49 return $cache[$key] . '/' . $code;
50 } else {
51 return $cache[$key];
52 }
53 }
54
61 public static function figureMessage( string $text ): array {
62 $pos = strrpos( $text, '/' );
63 $code = substr( $text, $pos + 1 );
64 $key = substr( $text, 0, $pos );
65
66 return [ $key, $code ];
67 }
68
76 public static function getMessageContent( string $key, string $language, int $namespace = NS_MEDIAWIKI ): ?string {
77 $title = self::title( $key, $language, $namespace );
78 $data = self::getContents( [ $title ], $namespace );
79
80 return $data[$title][0] ?? null;
81 }
82
92 private static function fetchLatestRevisionsByTitles( array $titles, int $namespace ): array {
93 $mwServices = MediaWikiServices::getInstance();
94 $dbr = $mwServices->getConnectionProvider()->getReplicaDatabase();
95 $revStore = $mwServices->getRevisionStore();
96
97 $rows = $revStore->newSelectQueryBuilder( $dbr )
98 ->joinPage()
99 ->joinComment()
100 ->where( [ 'page_namespace' => $namespace, 'page_title' => $titles, 'page_latest=rev_id' ] )
101 ->caller( __METHOD__ )
102 ->fetchResultSet();
103
104 $revisions = $revStore->newRevisionsFromBatch( $rows, [
105 'slots' => true,
106 'content' => true
107 ] )->getValue();
108
109 $result = [];
110 foreach ( $rows as $row ) {
111 $revision = $revisions[$row->rev_id] ?? null;
112 if ( $revision !== null ) {
113 $content = $revision->getContent( SlotRecord::MAIN );
114 if ( $content instanceof TextContent ) {
115 $result[$row->page_title] = $revision;
116 }
117 }
118 }
119
120 $rows->free();
121
122 return $result;
123 }
124
133 public static function getContents( $titles, int $namespace ): array {
134 $titleContents = [];
135 foreach ( self::fetchLatestRevisionsByTitles( (array)$titles, $namespace ) as $pageTitle => $revision ) {
136 $user = $revision->getUser( RevisionRecord::FOR_PUBLIC );
137 $titleContents[$pageTitle] = [
138 self::getTextFromTextContent( $revision->getContent( SlotRecord::MAIN ) ),
139 $user ? $user->getName() : '',
140 ];
141 }
142
143 return $titleContents;
144 }
145
152 public static function getContentForTitle( Title $title, bool $addFuzzy = false ): ?string {
153 $revision = MediaWikiServices::getInstance()->getRevisionStore()->getRevisionByTitle( $title );
154 $wiki = self::getTextFromContentOrNull( $revision?->getContent( SlotRecord::MAIN ) );
155 if ( $wiki === null ) {
156 return null;
157 }
158
159 if ( $addFuzzy ) {
160 $handle = new MessageHandle( $title );
161 if ( $handle->isFuzzy() ) {
162 $wiki = TRANSLATE_FUZZY . str_replace( TRANSLATE_FUZZY, '', $wiki );
163 }
164 }
165
166 return $wiki;
167 }
168
169 /* Some other helpers for output */
170
177 public static function getLanguageName( string $code, ?string $language = 'en' ): string {
178 $languages = self::getLanguageNames( $language );
179 return $languages[$code] ?? $code;
180 }
181
189 public static function getLanguageNames( ?string $code ): array {
190 $mwServices = MediaWikiServices::getInstance();
191 $languageNames = array_diff_key(
192 $mwServices->getLanguageNameUtils()->getLanguageNames( $code ),
193 LanguageCode::getDeprecatedCodeMapping()
194 );
195 Services::getInstance()->getHookRunner()->onTranslateSupportedLanguages( $languageNames, $code );
196
197 return $languageNames;
198 }
199
207 public static function fieldset( string $legend, string $contents, array $attributes = [] ): string {
208 return Html::rawElement(
209 'fieldset',
210 $attributes,
211 Html::rawElement( 'legend', [], $legend ) . $contents
212 );
213 }
214
226 public static function convertWhiteSpaceToHTML( string $message ): string {
227 $msg = htmlspecialchars( $message );
228 $msg = preg_replace( '/^ /m', '&#160;', $msg );
229 $msg = preg_replace( '/ $/m', '&#160;', $msg );
230 $msg = preg_replace( '/ /', '&#160; ', $msg );
231 $msg = str_replace( "\n", '<br />', $msg );
232
233 return $msg;
234 }
235
241 public static function cacheFile( string $filename ): string {
242 global $wgTranslateCacheDirectory, $wgCacheDirectory;
243
244 if ( $wgTranslateCacheDirectory !== false ) {
245 $dir = $wgTranslateCacheDirectory;
246 } elseif ( $wgCacheDirectory !== false ) {
247 $dir = $wgCacheDirectory;
248 } else {
249 throw new ConfigException( "\$wgCacheDirectory must be configured" );
250 }
251
252 return "$dir/$filename";
253 }
254
256 public static function getPlaceholder(): string {
257 static $i = 0;
258
259 return "\x7fUNIQ" . dechex( mt_rand( 0, 0x7fffffff ) ) .
260 dechex( mt_rand( 0, 0x7fffffff ) ) . '-' . $i++;
261 }
262
269 public static function getIcon( MessageGroup $g, int $size ): ?array {
270 $icon = $g->getIcon();
271 if ( !$icon || substr( $icon, 0, 7 ) !== 'wiki://' ) {
272 return null;
273 }
274
275 $formats = [];
276
277 $filename = substr( $icon, 7 );
278 $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $filename );
279 if ( !$file ) {
280 wfWarn( "Unknown message group icon file $icon" );
281
282 return null;
283 }
284
285 if ( $file->isVectorized() ) {
286 $formats['vector'] = $file->getFullUrl();
287 }
288
289 $formats['raster'] = $file->createThumb( $size, $size );
290
291 return $formats;
292 }
293
300 public static function getSafeReadDB(): IReadableDatabase {
301 $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
302 $index = self::shouldReadFromPrimary() ? DB_PRIMARY : DB_REPLICA;
303
304 return $lb->getConnection( $index );
305 }
306
308 public static function shouldReadFromPrimary(): bool {
309 $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
310 // Parsing APIs need POST for payloads but are read-only, so avoid spamming
311 // the primary then. No good way to check this at the moment...
312 if ( PageTranslationHooks::$renderingContext ) {
313 return false;
314 }
315
316 return PHP_SAPI === 'cli' ||
317 RequestContext::getMain()->getRequest()->wasPosted() ||
318 $lb->hasOrMadeRecentPrimaryChanges();
319 }
320
329 public static function getEditorUrl(
330 MessageHandle $handle,
331 string $action_source = '',
332 bool $includeLanguageParam = true
333 ): string {
334 if ( !$handle->isValid() ) {
335 return $handle->getTitle()->getLocalURL( [ 'action' => 'edit' ] );
336 }
337
338 $title = MediaWikiServices::getInstance()
339 ->getSpecialPageFactory()->getPage( 'Translate' )->getPageTitle();
340 $urlParameters = [
341 'showMessage' => $handle->getInternalKey(),
342 'group' => $handle->getGroup()->getId(),
343 'language' => $includeLanguageParam ? $handle->getCode() : null,
344 ];
345
346 if ( $action_source !== '' ) {
347 $urlParameters[ 'action_source' ] = $action_source;
348 }
349
350 return $title->getFullURL( $urlParameters );
351 }
352
357 public static function serialize( $value ): string {
358 return serialize( $value );
359 }
360
365 public static function deserialize( string $str, array $opts = [ 'allowed_classes' => false ] ) {
366 return unserialize( $str, $opts );
367 }
368
369 public static function getVersion(): string {
370 // Avoid parsing JSON multiple time per request
371 static $version = null;
372 $version ??= json_decode( file_get_contents( __DIR__ . '../../../extension.json' ) )->version;
373 return $version;
374 }
375
383 public static function allowsSubpages( Title $title ): bool {
384 $mwInstance = MediaWikiServices::getInstance();
385 $namespaceInfo = $mwInstance->getNamespaceInfo();
386 return $namespaceInfo->hasSubpages( $title->getNamespace() );
387 }
388
395 public static function isSupportedLanguageCode( string $code ): bool {
396 $all = self::getLanguageNames( LanguageNameUtils::AUTONYMS );
397 return isset( $all[ $code ] );
398 }
399
405 public static function getTextFromContentOrNull( ?Content $content ): ?string {
406 return $content instanceof TextContent ? $content->getText() : null;
407 }
408
414 public static function getTextFromTextContent( ?Content $content ): string {
415 if ( !$content ) {
416 throw new UnexpectedValueException( 'Expected $content to be TextContent, got null instead.' );
417 }
418
419 if ( $content instanceof TextContent ) {
420 return $content->getText();
421 }
422
423 throw new UnexpectedValueException( 'Expected $content to be TextContent, but got ' . get_class( $content ) );
424 }
425
432 public static function getTranslations( MessageHandle $handle ): array {
433 $titleContents = [];
434 foreach ( self::getTranslationRevisions( $handle ) as $pageTitle => $revision ) {
435 $user = $revision->getUser( RevisionRecord::FOR_PUBLIC );
436 $titleContents[$pageTitle] = [
437 self::getTextFromTextContent( $revision->getContent( SlotRecord::MAIN ) ),
438 $user ? $user->getName() : '',
439 ];
440 }
441
442 return $titleContents;
443 }
444
458 public static function getTranslationRevisions( MessageHandle $handle ): array {
459 $namespace = $handle->getTitle()->getNamespace();
460 $base = $handle->getKey();
461
462 $dbr = MediaWikiServices::getInstance()->getConnectionProvider()->getReplicaDatabase();
463
464 $titles = $dbr->newSelectQueryBuilder()
465 ->select( 'page_title' )
466 ->from( 'page' )
467 ->where( [
468 'page_namespace' => $namespace,
469 'page_title ' . $dbr->buildLike( "$base/", $dbr->anyString() ),
470 ] )
471 ->caller( __METHOD__ )
472 ->orderBy( 'page_title' )
473 ->fetchFieldValues();
474
475 if ( $titles === [] ) {
476 return [];
477 }
478
479 // fetchLatestRevisionsByTitles may return results in a different order
480 // (by rev_id or row insertion), so re-index in the original page_title order.
481 $revisionsByTitle = self::fetchLatestRevisionsByTitles( $titles, $namespace );
482 $ordered = [];
483 foreach ( $titles as $title ) {
484 if ( isset( $revisionsByTitle[$title] ) ) {
485 $ordered[$title] = $revisionsByTitle[$title];
486 }
487 }
488 return $ordered;
489 }
490
491 public static function isTranslationPage( MessageHandle $handle ): bool {
492 // FIXME: A lot of this code is similar to TranslatablePage::isTranslationPage.
493 // See if they can be merged
494 // The major difference is that this method does not run a database query to check if
495 // the page is marked.
496 $key = $handle->getKey();
497 $languageCode = $handle->getCode();
498 if ( $key === '' || $languageCode === '' ) {
499 return false;
500 }
501
502 $baseTitle = Title::makeTitle( $handle->getTitle()->getNamespace(), $key );
503 if ( !TranslatablePage::isSourcePage( $baseTitle ) ) {
504 return false;
505 }
506
507 static $codes = null;
508 $codes ??= self::getLanguageNames( LanguageNameUtils::AUTONYMS );
509
510 return !$handle->isDoc() && isset( $codes[ $languageCode ] );
511 }
512
520 public static function isValidRegex( string $pattern, ?string &$error = null ): bool {
521 set_error_handler( static function ( $severity, $message ) use ( &$error ) {
522 $error = $message;
523 return true;
524 } );
525
526 try {
527 // @phan-suppress-next-line PhanParamSuspiciousOrder
528 $result = preg_match( $pattern, '' );
529 return $result !== false;
530 } finally {
531 restore_error_handler();
532 }
533 }
534}
535
536class_alias( Utilities::class, 'TranslateUtils' );
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->getConnectionProvider());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
Class for pointing to messages, like Title class is for titles.
getKey()
Returns the identified or guessed message key.
Mixed bag of methods related to translatable pages.
Minimal service container.
Definition Services.php:60
Essentially random collection of helper functions, similar to GlobalFunctions.php.
Definition Utilities.php:30
static getPlaceholder()
Returns a random string that can be used as placeholder in strings.
static allowsSubpages(Title $title)
Checks if the namespace that the title belongs to allows subpages.
static getIcon(MessageGroup $g, int $size)
Get URLs for icons if available.
static getMessageContent(string $key, string $language, int $namespace=NS_MEDIAWIKI)
Loads page content without side effects.
Definition Utilities.php:76
static getTranslationRevisions(MessageHandle $handle)
Returns the latest RevisionRecord for each existing translation of a message.
static getLanguageName(string $code, ?string $language='en')
Returns a localised language name.
static fieldset(string $legend, string $contents, array $attributes=[])
Constructs a fieldset with contents.
static isSupportedLanguageCode(string $code)
Checks whether a language code is supported for translation at the wiki level.
static getTranslations(MessageHandle $handle)
Returns all translations of a given message.
static getContentForTitle(Title $title, bool $addFuzzy=false)
Returns the content for a given title and adds the fuzzy tag if requested.
static getSafeReadDB()
Get a DB handle suitable for read and read-for-write cases.
static getEditorUrl(MessageHandle $handle, string $action_source='', bool $includeLanguageParam=true)
Get a URL that points to an editor for this message handle.
static getContents( $titles, int $namespace)
Fetches contents for page names in given namespace.
static shouldReadFromPrimary()
Check whether primary should be used for reads to avoid reading stale data.
static getTextFromTextContent(?Content $content)
Strict extraction of text from content.
static isValidRegex(string $pattern, ?string &$error=null)
Validate a regular exception.
static serialize( $value)
Serialize the given value.
static cacheFile(string $filename)
Gets the path for cache files.
static convertWhiteSpaceToHTML(string $message)
Escapes the message, and does some mangling to whitespace, so that it is preserved when outputted as-...
static deserialize(string $str, array $opts=[ 'allowed_classes'=> false])
Deserialize the given string.
static title(string $message, string $code, int $ns=NS_MEDIAWIKI)
Does quick normalisation of message name so that in can be looked from the database.
Definition Utilities.php:39
static getTextFromContentOrNull(?Content $content)
Best-effort extraction of text from content.
static figureMessage(string $text)
Splits page name into message key and language code.
Definition Utilities.php:61
static getLanguageNames(?string $code)
Get translated language names for the languages generally supported for translation in the current wi...
Interface for message groups.