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;
16use MediaWiki\Title\Title;
17use MessageGroup;
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 $handle = new MessageHandle( Title::newFromText( $pagename ) );
122 $item['editorUrl'] = Utilities::getEditorUrl( $handle );
123 $item['location'] = $handle->getTitle()->getPrefixedText();
124 }
125 }
126 return $items;
127 }
128
129 protected function formatInternalSuggestions(
130 array $queryData,
131 ReadableTtmServer $s,
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'] ??= $s->expandLocation( $item );
145 if ( $local ) {
146 $handle = new MessageHandle( Title::newFromText( $item[ 'location' ] ) );
147 $item['editorUrl'] = Utilities::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 // Remove writable services
195 $writableServices = $this->ttmServerFactory->getWriteOnly();
196 foreach ( array_keys( $writableServices ) as $serviceId ) {
197 unset( $services[ $serviceId ] );
198 }
199
200 // Then remove non-ttmservers
201 foreach ( $services as $name => $config ) {
202 $type = $config['type'];
203 if ( $type !== 'ttmserver' && $type !== 'remote-ttmserver' ) {
204 unset( $services[$name] );
205 }
206 }
207
208 // Then determine the query method. Prefer HTTP queries that can be run parallel.
209 foreach ( $services as $name => &$config ) {
210 $public = $config['public'] ?? false;
211 if ( $config['type'] === 'ttmserver' && $public ) {
212 $config['type'] = 'remote-ttmserver';
213 $config['service'] = $name;
214 $config['url'] = wfExpandUrl( wfScript( 'api' ), PROTO_CANONICAL );
215 }
216 }
217
218 return $services;
219 }
220}
Class for pointing to messages, like Title class is for titles.
Minimal service container.
Definition Services.php:58
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...
Essentially random collection of helper functions, similar to GlobalFunctions.php.
Definition Utilities.php:31
Some general static methods for instantiating TTMServer and helpers.
Definition TTMServer.php:20
static sortSuggestions(array $suggestions)
Definition TTMServer.php:33
Interface for TTMServer that can be queried (=all of them).
Interface for message groups.