Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
TTMServerAid.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\TranslatorInterface\Aid;
5
6use Exception;
7use IContextSource;
13use MessageGroup;
16use Title;
18use TTMServer;
19
29 private $services;
31 private $ttmServerFactory;
32
33 public function __construct(
34 MessageGroup $group,
35 MessageHandle $handle,
36 IContextSource $context,
37 TranslationAidDataProvider $dataProvider
38 ) {
39 parent::__construct( $group, $handle, $context, $dataProvider );
40 $this->ttmServerFactory = Services::getInstance()->getTtmServerFactory();
41 }
42
43 public function populateQueries(): void {
44 $text = $this->dataProvider->getDefinition();
45 $from = $this->group->getSourceLanguage();
46 $to = $this->handle->getCode();
47
48 if ( trim( $text ) === '' ) {
49 return;
50 }
51
52 foreach ( $this->getWebServices() as $service ) {
53 $this->storeQuery( $service, $from, $to, $text );
54 }
55 }
56
57 public function getData(): array {
58 $text = $this->dataProvider->getDefinition();
59 if ( trim( $text ) === '' ) {
60 return [];
61 }
62
63 $suggestions = [];
64 $from = $this->group->getSourceLanguage();
65 $to = $this->handle->getCode();
66
67 foreach ( $this->getInternalServices() as $name => $service ) {
68 try {
69 $queryData = $service->query( $from, $to, $text );
70 } catch ( TranslationHelperException $e ) {
71 throw $e;
72 } catch ( Exception $e ) {
73 // Not ideal to catch all exceptions
74 continue;
75 }
76
77 $sugs = $this->formatInternalSuggestions( $queryData, $service, $name, $from );
78 $suggestions = array_merge( $suggestions, $sugs );
79 }
80
81 // Results from web services
82 foreach ( $this->getQueryData() as $queryData ) {
83 $sugs = $this->formatWebSuggestions( $queryData );
84 $suggestions = array_merge( $suggestions, $sugs );
85 }
86
87 $suggestions = TTMServer::sortSuggestions( $suggestions );
88 // Must be here to not mess up the sorting function
89 $suggestions['**'] = 'suggestion';
90
91 return $suggestions;
92 }
93
94 protected function formatWebSuggestions( array $queryData ): array {
95 $service = $queryData['service'];
96 $response = $queryData['response'];
97 $sourceLanguage = $queryData['language'];
98 $sourceText = $queryData['text'];
99
100 // getResultData returns a null on failure instead of throwing an exception
101 $items = $service->getResultData( $response );
102 if ( $items === null ) {
103 return [];
104 }
105
106 $localPrefix = Title::makeTitle( NS_MAIN, '' )->getFullURL( '', false, PROTO_CANONICAL );
107 $localPrefixLength = strlen( $localPrefix );
108
109 foreach ( $items as &$item ) {
110 $local = strncmp( $item['uri'], $localPrefix, $localPrefixLength ) === 0;
111 $item = array_merge( $item, [
112 'service' => $service->getName(),
113 'source_language' => $sourceLanguage,
114 'source' => $sourceText,
115 'local' => $local,
116 ] );
117
118 // TtmServerActionApi expands this... need to fix it again to be the bare name
119 if ( $local ) {
120 $pagename = urldecode( substr( $item['location'], $localPrefixLength ) );
121 $item['location'] = $pagename;
122 $handle = new MessageHandle( Title::newfromText( $pagename ) );
123 $item['editorUrl'] = TranslateUtils::getEditorUrl( $handle );
124 }
125 }
126 return $items;
127 }
128
129 protected function formatInternalSuggestions(
130 array $queryData,
132 string $serviceName,
133 string $sourceLanguage
134 ): array {
135 $items = [];
136
137 foreach ( $queryData as $item ) {
138 $local = $s->isLocalSuggestion( $item );
139
140 $item['service'] = $serviceName;
141 $item['source_language'] = $sourceLanguage;
142 $item['local'] = $local;
143 // Likely only needed for non-public DatabaseTTMServer
144 $item['uri'] = $item['uri'] ?? $s->expandLocation( $item );
145 if ( $local ) {
146 $handle = new MessageHandle( Title::newfromText( $item[ 'location' ] ) );
147 $item['editorUrl'] = TranslateUtils::getEditorUrl( $handle );
148 }
149 $items[] = $item;
150 }
151
152 return $items;
153 }
154
156 private function getInternalServices(): array {
157 $services = $this->getQueryableServices();
158 foreach ( $services as $name => $config ) {
159 if ( $config['type'] === 'ttmserver' ) {
160 $services[$name] = $this->ttmServerFactory->create( $name );
161 } else {
162 unset( $services[$name] );
163 }
164 }
165
166 return $services;
167 }
168
170 private function getWebServices(): array {
171 $services = $this->getQueryableServices();
172 foreach ( $services as $name => $config ) {
173 if ( $config['type'] === 'remote-ttmserver' ) {
174 $services[$name] = TranslationWebService::factory( $name, $config );
175 } else {
176 unset( $services[$name] );
177 }
178 }
179
180 return $services;
181 }
182
183 private function getQueryableServices(): array {
184 if ( !$this->services ) {
185 global $wgTranslateTranslationServices;
186 $this->services = $this->getQueryableServicesUncached(
187 $wgTranslateTranslationServices );
188 }
189
190 return $this->services;
191 }
192
193 private function getQueryableServicesUncached( array $services ): array {
194 // First remove mirrors of the primary service
195 $primary = $this->ttmServerFactory->getDefault();
196 $mirrors = $primary->getMirrors();
197 foreach ( $mirrors as $mirrorName ) {
198 unset( $services[$mirrorName] );
199 }
200
201 // Then remove non-ttmservers
202 foreach ( $services as $name => $config ) {
203 $type = $config['type'];
204 if ( $type !== 'ttmserver' && $type !== 'remote-ttmserver' ) {
205 unset( $services[$name] );
206 }
207 }
208
209 // Then determine the query method. Prefer HTTP queries that can be run parallel.
210 foreach ( $services as $name => &$config ) {
211 $public = $config['public'] ?? false;
212 if ( $config['type'] === 'ttmserver' && $public ) {
213 $config['type'] = 'remote-ttmserver';
214 $config['service'] = $name;
215 $config['url'] = wfExpandUrl( wfScript( 'api' ), PROTO_CANONICAL );
216 }
217 }
218
219 return $services;
220 }
221}
Minimal service container.
Definition Services.php:38
storeQuery(TranslationWebService $service, string $from, string $to, string $text)
Stores a web service query for later execution.
Translation aid that provides suggestion from translation memory.
getData()
Translation aid class should implement this function.
Translation helpers can throw this exception when they cannot do anything useful with the current mes...
Class for pointing to messages, like Title class is for titles.
Some general static methods for instantiating TTMServer and helpers.
Definition TTMServer.php:20
static sortSuggestions(array $suggestions)
Definition TTMServer.php:71
Essentially random collection of helper functions, similar to GlobalFunctions.php.
static getEditorUrl(MessageHandle $handle)
Get an URL that points to an editor for this message handle.
Interface for message groups.
Interface for TTMServer that can be queried (=all of them).
expandLocation(array $suggestion)
Given suggestion returned by this TTMServer, constructs fully qualified URL to the location of the tr...
isLocalSuggestion(array $suggestion)
Determines if the suggestion returned by this TTMServer comes from this wiki or any other wiki.