import { format } from 'util' ; import * as request from 'request' ; import { Observable } from 'rxjs' ; import { of , forkJoin , throwError } from 'rxjs' ; import { map } from 'rxjs/operators' ; /**
 * Created by roobm on 03.07.2017.
 * Low Level Service to call Google Translate.
 */ /**
 * Types form google translate api.
 */ interface GetSupportedLanguagesRequest { target : string ; } interface LanguagesResource { language : string ; name : string ; } interface LanguagesListResponse { languages : LanguagesResource [ ] ; } interface TranslateTextRequest { q : string [ ] ; target : string ; source : string ; format ? : string ; model ? : string ; } interface TranslationsResource { detectedSourceLanguage ? : string ; model ? : string ; translatedText : string ; } interface TranslationsListResponse { translations : TranslationsResource [ ] ; } interface InternalRequestResponse { response : request . RequestResponse ; body : any ; } const MAX_SEGMENTS = 128 ; export class AutoTranslateService { private _request : request . RequestAPI < request . Request , request . CoreOptions , request . RequiredUriUrl > ; _rootUrl : string ; _apiKey : string ; param lang return public static stripRegioncode ( lang ) { const langLower = lang . toLowerCase ( ) ; for ( let i = 0 ; i < langLower . length ; i ++ ) { const c = langLower . charAt ( i ) ; if ( c < 'a' || c > 'z' ) { return langLower . substring ( 0 , i ) ; } } return langLower ; } constructor ( apiKey ) { this . _request = request ; this . _apiKey = apiKey ; this . _rootUrl = 'https://translation.googleapis.com/' ; } param apikey public setApiKey ( apikey ) { this . _apiKey = apikey ; } param messages param from param to return public translateMultipleStrings ( messages , from , to ) { if ( messages . length === 0 ) { return of ( [ ] ) ; } if ( ! this . _apiKey ) { return throwError ( 'cannot autotranslate: no api key' ) ; } if ( ! from || ! to ) { return throwError ( 'cannot autotranslate: source and target language must be set' ) ; } from = AutoTranslateService . stripRegioncode ( from ) ; to = AutoTranslateService . stripRegioncode ( to ) ; const allRequests = this . splitMessagesToGoogleLimit ( messages ) . map ( ( partialMessages ) => { return this . limitedTranslateMultipleStrings ( partialMessages , from , to ) ; } ) ; return forkJoin ( allRequests ) . pipe ( map ( ( allTranslations ) => { let all = [ ] ; for ( let i = 0 ; i < allTranslations . length ; i ++ ) { all = all . concat ( allTranslations [ i ] ) ; } return all ; } ) ) ; } private splitMessagesToGoogleLimit ( messages ) { if ( messages . length <= MAX_SEGMENTS ) { return [ messages ] ; } const result = [ ] ; let currentPackage = [ ] ; let packageSize = 0 ; for ( let i = 0 ; i < messages . length ; i ++ ) { currentPackage . push ( messages [ i ] ) ; packageSize ++ ; if ( packageSize >= MAX_SEGMENTS ) { result . push ( currentPackage ) ; currentPackage = [ ] ; packageSize = 0 ; } } if ( currentPackage . length > 0 ) { result . push ( currentPackage ) ; } return result ; } param messages param from param to return private limitedTranslateMultipleStrings ( messages , from , to ) { const realUrl = this . _rootUrl + 'language/translate/v2' + '?key=' + this . _apiKey ; const translateRequest = { q : messages , target : to , source : from , } ; const options = { url : realUrl , body : translateRequest , json : true , } ; return this . post ( realUrl , options ) . pipe ( map ( ( data ) => { const body = data . body ; if ( ! body ) { throw new Error ( 'no result received' ) ; } if ( body . error ) { if ( body . error . code === 400 ) { if ( body . error . message === 'Invalid Value' ) { throw new Error ( format ( 'Translation from "%s" to "%s" not supported' , from , to ) ) ; } throw new Error ( format ( 'Invalid request: %s' , body . error . message ) ) ; } else { throw new Error ( format ( 'Error %s: %s' , body . error . code , body . error . message ) ) ; } } const result = body . data ; return result . translations . map ( ( translation ) => { return translation . translatedText ; } ) ; } ) ) ; } param uri param options return post ( uri , options ? ) { return < Observable < InternalRequestResponse > > this . _call . apply ( this , [ ] . concat ( 'post' , < string > uri , < request . CoreOptions > Object . assign ( { } , options || { } ) ) ) ; } param method param uri param options return private _call ( method , uri , options ? ) { return < Observable < InternalRequestResponse > > Observable . create ( ( observer ) => { const params = [ ] . concat ( < string > uri , < request . CoreOptions > Object . assign ( { } , options || { } ) , < RequestCallback > ( error , response , body ) => { if ( error ) { return observer . error ( error ) ; } observer . next ( < InternalRequestResponse > Object . assign ( { } , { response : < request . RequestResponse > response , body : < any > body } ) ) ; observer . complete ( ) ; } ) ; try { this . _request [ < string > method ] . apply ( < request . RequestAPI < request . Request , request . CoreOptions , request . RequiredUriUrl > > this . _request , params ) ; } catch ( error ) { observer . error ( error ) ; } } ) ; } }