Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
DatabaseTtmServer.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\TtmServer;
5
8use MediaWiki\MediaWikiServices;
9use MediaWiki\Title\Title;
10use MediaWiki\WikiMap\WikiMap;
11use Wikimedia\Rdbms\DBQueryError;
12use Wikimedia\Rdbms\IDatabase;
13use Wikimedia\Rdbms\IReadableDatabase;
14use Wikimedia\Rdbms\IResultWrapper;
15
24 private array $sids;
25
26 private function getDB( int $mode = DB_REPLICA ): IDatabase|IReadableDatabase {
27 $connectionProvider = MediaWikiServices::getInstance()->getConnectionProvider();
28
29 if ( $mode === DB_REPLICA ) {
30 return $connectionProvider->getReplicaDatabase( $this->config['database'] );
31 }
32
33 return $connectionProvider->getPrimaryDatabase( $this->config['database'] );
34 }
35
36 public function update( MessageHandle $handle, ?string $targetText ): bool {
37 if ( !$handle->isValid() || $handle->getCode() === '' ) {
38 return false;
39 }
40
41 $mKey = $handle->getKey();
42 $group = $handle->getGroup();
43 $targetLanguage = $handle->getCode();
44 $sourceLanguage = $group->getSourceLanguage();
45
46 // Skip definitions to not slow down mass imports etc.
47 // These will be added when the first translation is made
48 if ( $targetLanguage === $sourceLanguage ) {
49 return false;
50 }
51
52 $definition = $group->getMessage( $mKey, $sourceLanguage );
53 if ( !is_string( $definition ) || !strlen( trim( $definition ) ) ) {
54 return false;
55 }
56
57 $context = Title::makeTitle( $handle->getTitle()->getNamespace(), $mKey );
58 $dbw = $this->getDB( DB_PRIMARY );
59 /* Check that the definition exists and fetch the sid. If not, add
60 * the definition and retrieve the sid. If the definition changes,
61 * we will create a new entry - otherwise we could at some point
62 * get suggestions which do not match the original definition any
63 * longer. The old translations are still kept until purged by
64 * rerunning the bootstrap script. */
65 $sid = $dbw->newSelectQueryBuilder()
66 ->select( 'tms_sid' )
67 ->from( 'translate_tms' )
68 ->where( [
69 'tms_context' => $context->getPrefixedText(),
70 'tms_text' => $definition,
71 ] )
72 ->caller( __METHOD__ )
73 ->fetchField();
74 if ( $sid === false ) {
75 $sid = $this->insertSource( $context, $sourceLanguage, $definition );
76 }
77
78 // Delete old translations for this message if any. Could also use replace
79 $deleteConditions = [
80 'tmt_sid' => $sid,
81 'tmt_lang' => $targetLanguage,
82 ];
83 $dbw->newDeleteQueryBuilder()
84 ->deleteFrom( 'translate_tmt' )
85 ->where( $deleteConditions )
86 ->caller( __METHOD__ )
87 ->execute();
88
89 // Insert the new translation
90 if ( $targetText !== null ) {
91 $row = $deleteConditions + [
92 'tmt_text' => $targetText,
93 ];
94
95 $dbw->newInsertQueryBuilder()
96 ->insertInto( 'translate_tmt' )
97 ->row( $row )
98 ->caller( __METHOD__ )
99 ->execute();
100 }
101
102 return true;
103 }
104
105 private function insertSource( Title $context, string $sourceLanguage, string $text ): int {
106 $dbw = $this->getDB( DB_PRIMARY );
107 $dbw->newInsertQueryBuilder()
108 ->insertInto( 'translate_tms' )
109 ->row( [
110 'tms_lang' => $sourceLanguage,
111 'tms_len' => mb_strlen( $text ),
112 'tms_text' => $text,
113 'tms_context' => $context->getPrefixedText(),
114 ] )
115 ->caller( __METHOD__ )
116 ->execute();
117 $sid = $dbw->insertId();
118
119 $fulltext = $this->filterForFulltext( $sourceLanguage, $text );
120 if ( count( $fulltext ) ) {
121 $dbw->newInsertQueryBuilder()
122 ->insertInto( 'translate_tmf' )
123 ->row( [
124 'tmf_sid' => $sid,
125 'tmf_text' => implode( ' ', $fulltext ),
126 ] )
127 ->caller( __METHOD__ )
128 ->execute();
129 }
130
131 return $sid;
132 }
133
135 protected function filterForFulltext( string $languageCode, string $input ): array {
136 $lang = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( $languageCode );
137
138 $text = preg_replace( '/[^[:alnum:]]/u', ' ', $input );
139 $text = $lang->segmentByWord( $text );
140 $text = $lang->lc( $text );
141 $segments = preg_split( '/\s+/', $text, -1, PREG_SPLIT_NO_EMPTY );
142 if ( count( $segments ) < 4 ) {
143 return [];
144 }
145
146 foreach ( $segments as $i => $segment ) {
147 // Yes strlen
148 $len = strlen( $segment );
149 if ( $len < 4 || $len > 15 ) {
150 unset( $segments[$i] );
151 }
152 }
153
154 return array_slice( array_unique( $segments ), 0, 10 );
155 }
156
157 public function beginBootstrap(): void {
158 $dbw = $this->getDB( DB_PRIMARY );
159 $dbw->newDeleteQueryBuilder()
160 ->deleteFrom( 'translate_tms' )
161 ->where( '*' )
162 ->caller( __METHOD__ )
163 ->execute();
164 $dbw->newDeleteQueryBuilder()
165 ->deleteFrom( 'translate_tmt' )
166 ->where( '*' )
167 ->caller( __METHOD__ )
168 ->execute();
169 $dbw->newDeleteQueryBuilder()
170 ->deleteFrom( 'translate_tmf' )
171 ->where( '*' )
172 ->caller( __METHOD__ )
173 ->execute();
174 $table = $dbw->tableName( 'translate_tmf' );
175 try {
176 $dbw->query( "DROP INDEX tmf_text ON $table", __METHOD__ );
177 } catch ( DBQueryError ) {
178 // Perhaps the script was aborted before it got
179 // chance to add the index back.
180 }
181 }
182
183 public function beginBatch(): void {
184 $this->sids = [];
185 }
186
187 public function batchInsertDefinitions( array $batch ): void {
188 $mwInstance = MediaWikiServices::getInstance();
189 $titleFactory = $mwInstance->getTitleFactory();
190 foreach ( $batch as $key => $item ) {
191 [ $handle, $language, $text ] = $item;
192 $context = $titleFactory->makeTitle( $handle->getTitle()->getNamespace(), $handle->getKey() );
193 $this->sids[$key] = $this->insertSource( $context, $language, $text );
194 }
195
196 $mwInstance->getDBLoadBalancerFactory()->waitForReplication( [ 'ifWritesSince' => 10 ] );
197 }
198
199 public function batchInsertTranslations( array $batch ): void {
200 if ( $batch === [] ) {
201 return;
202 }
203 $rows = [];
204 foreach ( $batch as $key => $data ) {
205 [ , $language, $text ] = $data;
206 $rows[] = [
207 'tmt_sid' => $this->sids[$key],
208 'tmt_lang' => $language,
209 'tmt_text' => $text,
210 ];
211 }
212
213 $dbw = $this->getDB( DB_PRIMARY );
214 $dbw->newInsertQueryBuilder()
215 ->insertInto( 'translate_tmt' )
216 ->rows( $rows )
217 ->caller( __METHOD__ )
218 ->execute();
219
220 MediaWikiServices::getInstance()
221 ->getDBLoadBalancerFactory()
222 ->waitForReplication( [ 'ifWritesSince' => 10 ] );
223 }
224
225 public function endBatch(): void {
226 }
227
228 public function endBootstrap(): void {
229 $dbw = $this->getDB( DB_PRIMARY );
230 $table = $dbw->tableName( 'translate_tmf' );
231 $dbw->query( "CREATE FULLTEXT INDEX tmf_text ON $table (tmf_text)", __METHOD__ );
232 }
233
234 /* Reading interface */
235
236 public function isLocalSuggestion( array $suggestion ): bool {
237 return true;
238 }
239
240 public function expandLocation( array $suggestion ): string {
241 return Title::newFromText( $suggestion['location'] )->getCanonicalURL();
242 }
243
244 public function query( string $sourceLanguage, string $targetLanguage, string $text ): array {
245 // Calculate the bounds of the string length which are able
246 // to satisfy the cutoff percentage in edit distance.
247 $len = mb_strlen( $text );
248 $min = ceil( max( $len * $this->config['cutoff'], 2 ) );
249 $max = floor( $len / $this->config['cutoff'] );
250
251 // We could use fulltext index to narrow the results further
252 $dbr = $this->getDB();
253 $tables = [ 'translate_tmt', 'translate_tms' ];
254 $fields = [ 'tms_context', 'tms_text', 'tmt_lang', 'tmt_text' ];
255
256 $conditions = [
257 'tms_lang' => $sourceLanguage,
258 'tmt_lang' => $targetLanguage,
259 "tms_len BETWEEN $min AND $max",
260 'tms_sid = tmt_sid',
261 ];
262
263 $fulltext = $this->filterForFulltext( $sourceLanguage, $text );
264 if ( $fulltext ) {
265 $tables[] = 'translate_tmf';
266 $list = implode( ' ', $fulltext );
267 $conditions[] = 'tmf_sid = tmt_sid';
268 $conditions[] = "MATCH(tmf_text) AGAINST( '$list' )";
269 }
270
271 $res = $dbr->newSelectQueryBuilder()
272 ->tables( $tables )
273 ->select( $fields )
274 ->where( $conditions )
275 ->caller( __METHOD__ )
276 ->fetchResultSet();
277
278 return $this->processQueryResults( $res, $text, $targetLanguage );
279 }
280
281 private function processQueryResults( IResultWrapper $res, string $text, string $targetLanguage ): array {
282 $timeLimit = microtime( true ) + 5;
283
284 $lenA = mb_strlen( $text );
285 $results = [];
286 $stringComparator = new EditDistanceStringComparator();
287 foreach ( $res as $row ) {
288 if ( microtime( true ) > $timeLimit ) {
289 // Having no suggestions is better than preventing translation
290 // altogether by timing out the request :(
291 break;
292 }
293
294 $a = $text;
295 $b = $row->tms_text;
296 $lenB = mb_strlen( $b );
297 $len = min( $lenA, $lenB );
298 if ( $len > 600 ) {
299 // two strings of length 1500 ~ 10s
300 // two strings of length 2250 ~ 30s
301 $dist = $len;
302 } else {
303 $dist = $stringComparator->levenshtein( $a, $b, $lenA, $lenB );
304 }
305 $quality = 1 - ( $dist * 0.9 / $len );
306
307 if ( $quality >= $this->config['cutoff'] ) {
308 $results[] = [
309 'source' => $row->tms_text,
310 'target' => $row->tmt_text,
311 'context' => $row->tms_context,
312 'location' => $row->tms_context . '/' . $targetLanguage,
313 'quality' => $quality,
314 'wiki' => $row->tms_wiki ?? WikiMap::getCurrentWikiId(),
315 ];
316 }
317 }
318
319 return TTMServer::sortSuggestions( $results );
320 }
321
322 public function setDoReIndex(): void {
323 }
324}
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.
MySQL/MariaDB-based based backend for translation memory.
setDoReIndex()
Instruct the service to fully wipe the index and start from scratch.
expandLocation(array $suggestion)
Given suggestion returned by this TtmServer, constructs fully qualified URL to the location of the tr...
batchInsertDefinitions(array $batch)
Called multiple times per batch if necessary.
update(MessageHandle $handle, ?string $targetText)
Shovels the new translation into translation memory.
endBatch()
Called after every batch (MessageGroup).
query(string $sourceLanguage, string $targetLanguage, string $text)
Fetches all relevant suggestions for given text.
filterForFulltext(string $languageCode, string $input)
Tokenizes the text for fulltext search.
beginBatch()
Called before every batch (MessageGroup).
isLocalSuggestion(array $suggestion)
Determines if the suggestion returned by this TtmServer comes from this wiki or any other wiki.
beginBootstrap()
Called when starting to fill the translation memory.
batchInsertTranslations(array $batch)
Called multiple times per batch if necessary.
TtmServer - The Translate extension translation memory interface Some general static methods for inst...
Definition TtmServer.php:19
Smart string comparator that uses simple string comparison, and then the levenshtein algorithm to com...
Interface for TtmServer that can be queried (=all of them).
Interface for TtmServer that can be updated.