TranslationWebService.php
Go to the documentation of this file.00001 <?php
00020 abstract class TranslationWebService {
00021
00022
00031 public static function factory( $name, $config ) {
00032 $handlers = array(
00033 'microsoft' => 'MicrosoftWebService',
00034 'apertium' => 'ApertiumWebService',
00035 'yandex' => 'YandexWebService',
00036 'ttmserver' => 'RemoteTTMServerWebService',
00037 );
00038
00039 if ( !isset( $config['timeout'] ) ) {
00040 $config['timeout'] = 3;
00041 }
00042
00043 if ( isset( $handlers[$config['type']] ) ) {
00044 $class = $handlers[$config['type']];
00045
00046 return new $class( $name, $config );
00047 }
00048
00049 return null;
00050 }
00051
00066 public function getSuggestions( $translations, $sourceLanguage, $targetLanguage ) {
00067 if ( $this->checkTranslationServiceFailure() ) {
00068 return array();
00069 }
00070
00071 $from = $this->mapCode( $sourceLanguage );
00072 $to = $this->mapCode( $targetLanguage );
00073
00074 try {
00075 $results = array();
00076
00077
00078 $supported = $this->getSupportedLanguagePairs();
00079 if ( isset( $supported[$from][$to] ) && isset( $translations[$from] ) ) {
00080
00081
00082 $translations = array( $sourceLanguage => $translations[$from] );
00083 }
00084
00085
00086
00087 foreach ( $translations as $language => $text ) {
00088 $from = $this->mapCode( $language );
00089
00090 if ( isset( $supported[$from][$to] ) ) {
00091 $sug = $this->doRequest( $text, $from, $to );
00092 if ( strval( $sug === '' ) ) {
00093 continue;
00094 }
00095
00096 $results[] = array(
00097 'target' => $sug,
00098 'service' => $this->service,
00099 'source_language' => $language,
00100 'source' => $text,
00101 );
00102 }
00103
00104 if ( count( $results ) >= 3 ) {
00105 break;
00106 }
00107 }
00108
00109 return $results;
00110 } catch ( Exception $e ) {
00111 $this->reportTranslationServiceFailure( $e );
00112
00113 return array();
00114 }
00115 }
00116
00117
00118
00126 abstract protected function mapCode( $code );
00127
00135 abstract protected function doPairs();
00136
00145 abstract protected function doRequest( $text, $from, $to );
00146
00147
00148
00152 protected $service;
00153
00157 protected $config;
00158
00159 protected function __construct( $service, $config ) {
00160 $this->service = $service;
00161 $this->config = $config;
00162 }
00163
00167 protected function getSupportedLanguagePairs() {
00168 $key = wfMemckey( 'translate-tmsug-pairs-' . $this->service );
00169 $pairs = wfGetCache( CACHE_ANYTHING )->get( $key );
00170 if ( !is_array( $pairs ) ) {
00171 $pairs = $this->doPairs();
00172
00173 wfGetCache( CACHE_ANYTHING )->set( $key, $pairs, 60 * 60 * 24 );
00174 }
00175
00176 return $pairs;
00177 }
00178
00184 protected function wrapUntranslatable( $text ) {
00185 $pattern = '~%[^% ]+%|\$\d|{VAR:[^}]+}|{?{(PLURAL|GRAMMAR|GENDER):[^|]+\||%(\d\$)?[sd]~';
00186 $text = str_replace( "\n", "!N!", $text );
00187 $wrap = '<span class="notranslate" translate="no">\0</span>';
00188 $text = preg_replace( $pattern, $wrap, $text );
00189
00190 return $text;
00191 }
00192
00196 protected function unwrapUntranslatable( $text ) {
00197 $pattern = '~<span class="notranslate" translate="no">(.*?)</span>~';
00198 $text = str_replace( '!N!', "\n", $text );
00199 $text = preg_replace( $pattern, '\1', $text );
00200
00201 return $text;
00202 }
00203
00204
00205
00210 protected $serviceFailureCount = 5;
00215 protected $serviceFailurePeriod = 900;
00216
00221 public function checkTranslationServiceFailure() {
00222 $service = $this->service;
00223 $key = wfMemckey( "translate-service-$service" );
00224 $value = wfGetCache( CACHE_ANYTHING )->get( $key );
00225 if ( !is_string( $value ) ) {
00226 return false;
00227 }
00228 list( $count, $failed ) = explode( '|', $value, 2 );
00229
00230 if ( $failed + ( 2 * $this->serviceFailurePeriod ) < wfTimestamp() ) {
00231 if ( $count >= $this->serviceFailureCount ) {
00232 wfDebugLog( 'translationservices', "Translation service $service (was) restored" );
00233 }
00234 wfGetCache( CACHE_ANYTHING )->delete( $key );
00235
00236 return false;
00237 } elseif ( $failed + $this->serviceFailurePeriod < wfTimestamp() ) {
00238
00239
00240
00241
00242 return false;
00243 }
00244
00245
00246 return $count >= $this->serviceFailureCount;
00247 }
00248
00252 protected function reportTranslationServiceFailure( Exception $e ) {
00253 $service = $this->service;
00254 wfDebugLog(
00255 'translationservices',
00256 "Translation service $service problem: " . $e->getMessage()
00257 );
00258
00259 $key = wfMemckey( "translate-service-$service" );
00260 $value = wfGetCache( CACHE_ANYTHING )->get( $key );
00261 if ( !is_string( $value ) ) {
00262 $count = 0;
00263 } else {
00264 list( $count, ) = explode( '|', $value, 2 );
00265 }
00266
00267 $count += 1;
00268 $failed = wfTimestamp();
00269 wfGetCache( CACHE_ANYTHING )->set(
00270 $key,
00271 "$count|$failed",
00272 $this->serviceFailurePeriod * 5
00273 );
00274
00275 if ( $count == $this->serviceFailureCount ) {
00276 wfDebugLog( 'translationservices', "Translation service $service suspended" );
00277 } elseif ( $count > $this->serviceFailureCount ) {
00278 wfDebugLog( 'translationservices', "Translation service $service still suspended" );
00279 }
00280 }
00281 }