import { isNullOrUndefined } from '../common/util' ; import { Observable , forkJoin , of } from 'rxjs' ; import { map , catchError } from 'rxjs/operators' ; import * as entityDecoderLib from 'he' ; import { IICUMessage , IICUMessageTranslation , INormalizedMessage , ITranslationMessagesFile , ITransUnit , STATE_NEW } from '@ngx-i18nsupport/ngx-i18nsupport-lib' ; import { AutoTranslateService } from './auto-translate-service' ; import { AutoTranslateResult } from './auto-translate-result' ; import { AutoTranslateSummaryReport } from './auto-translate-summary-report' ; /**
 * Created by martin on 07.07.2017.
 * Service to autotranslate Transunits via Google Translate.
 */ export class XliffMergeAutoTranslateService { private autoTranslateService : AutoTranslateService ; constructor ( apikey ) { this . autoTranslateService = new AutoTranslateService ( apikey ) ; } param from param to param languageSpecificMessagesFile return public autoTranslate ( from , to , languageSpecificMessagesFile ) { return forkJoin ( [ this . doAutoTranslateNonICUMessages ( from , to , languageSpecificMessagesFile ) , ... this . doAutoTranslateICUMessages ( from , to , languageSpecificMessagesFile ) ] ) . pipe ( map ( ( summaries ) => { const summary = summaries [ 0 ] ; for ( let i = 1 ; i < summaries . length ; i ++ ) { summary . merge ( summaries [ i ] ) ; } return summary ; } ) ) ; } param languageSpecificMessagesFile return private allUntranslatedTUs ( languageSpecificMessagesFile ) { const allUntranslated = [ ] ; languageSpecificMessagesFile . forEachTransUnit ( ( tu ) => { if ( tu . targetState ( ) === STATE_NEW ) { allUntranslated . push ( tu ) ; } } ) ; return allUntranslated ; } private doAutoTranslateNonICUMessages ( from , to , languageSpecificMessagesFile ) { const allUntranslated = this . allUntranslatedTUs ( languageSpecificMessagesFile ) ; const allTranslatable = allUntranslated . filter ( ( tu ) => isNullOrUndefined ( tu . sourceContentNormalized ( ) . getICUMessage ( ) ) ) ; const allMessages = allTranslatable . map ( ( tu ) => { return tu . sourceContentNormalized ( ) . asDisplayString ( ) ; } ) ; return this . autoTranslateService . translateMultipleStrings ( allMessages , from , to ) . pipe ( map ( ( translations ) => translations . map ( encodedTranslation => entityDecoderLib . decode ( encodedTranslation ) ) ) , map ( ( translations ) => { const summary = new AutoTranslateSummaryReport ( from , to ) ; summary . setIgnored ( allUntranslated . length - allTranslatable . length ) ; for ( let i = 0 ; i < translations . length ; i ++ ) { const tu = allTranslatable [ i ] ; const translationText = translations [ i ] ; const result = this . autoTranslateNonICUUnit ( tu , translationText ) ; summary . addSingleResult ( tu , result ) ; } return summary ; } ) , catchError ( ( err ) => { const failSummary = new AutoTranslateSummaryReport ( from , to ) ; failSummary . setError ( err . message , allMessages . length ) ; return of ( failSummary ) ; } ) ) ; } private doAutoTranslateICUMessages ( from , to , languageSpecificMessagesFile ) { const allUntranslated = this . allUntranslatedTUs ( languageSpecificMessagesFile ) ; const allTranslatableICU = allUntranslated . filter ( ( tu ) => ! isNullOrUndefined ( tu . sourceContentNormalized ( ) . getICUMessage ( ) ) ) ; return allTranslatableICU . map ( ( tu ) => { return this . doAutoTranslateICUMessage ( from , to , tu ) ; } ) ; } param from param to param tu return private doAutoTranslateICUMessage ( from , to , tu ) { const icuMessage = tu . sourceContentNormalized ( ) . getICUMessage ( ) ; const categories = icuMessage . getCategories ( ) ; if ( categories . find ( ( category ) => ! isNullOrUndefined ( category . getMessageNormalized ( ) . getICUMessage ( ) ) ) ) { const summary = new AutoTranslateSummaryReport ( from , to ) ; summary . setIgnored ( 1 ) ; return of ( summary ) ; } const allMessages = categories . map ( ( category ) => category . getMessageNormalized ( ) . asDisplayString ( ) ) ; return this . autoTranslateService . translateMultipleStrings ( allMessages , from , to ) . pipe ( map ( ( translations ) => translations . map ( encodedTranslation => entityDecoderLib . decode ( encodedTranslation ) ) ) , map ( ( translations ) => { const summary = new AutoTranslateSummaryReport ( from , to ) ; const icuTranslation = { } ; for ( let i = 0 ; i < translations . length ; i ++ ) { icuTranslation [ categories [ i ] . getCategory ( ) ] = translations [ i ] ; } const result = this . autoTranslateICUUnit ( tu , icuTranslation ) ; summary . addSingleResult ( tu , result ) ; return summary ; } ) , catchError ( ( err ) => { const failSummary = new AutoTranslateSummaryReport ( from , to ) ; failSummary . setError ( err . message , allMessages . length ) ; return of ( failSummary ) ; } ) ) ; } private autoTranslateNonICUUnit ( tu , translatedMessage ) { return this . autoTranslateUnit ( tu , tu . sourceContentNormalized ( ) . translate ( translatedMessage ) ) ; } private autoTranslateICUUnit ( tu , translation ) { return this . autoTranslateUnit ( tu , tu . sourceContentNormalized ( ) . translateICUMessage ( translation ) ) ; } private autoTranslateUnit ( tu , translatedMessage ) { const errors = translatedMessage . validate ( ) ; const warnings = translatedMessage . validateWarnings ( ) ; if ( ! isNullOrUndefined ( errors ) ) { return new AutoTranslateResult ( false , 'errors detected, not translated' ) ; } else if ( ! isNullOrUndefined ( warnings ) ) { return new AutoTranslateResult ( false , 'warnings detected, not translated' ) ; } else { tu . translate ( translatedMessage ) ; return new AutoTranslateResult ( true , null ) ; } } }