import { STATE_NEW , STATE_TRANSLATED } from '../api/constants' ; import { ITranslationMessagesFile } from '../api/i-translation-messages-file' ; import { INormalizedMessage } from '../api/i-normalized-message' ; import { ITransUnit } from '../api/i-trans-unit' ; import { isNullOrUndefined } from 'util' ; import { DOMParser } from 'xmldom' ; import { XmlSerializer , XmlSerializerOptions } from './xml-serializer' ; /**
 * Created by roobm on 09.05.2017.
 * Abstract superclass for all implementations of ITranslationMessagesFile.
 */ export abstract class AbstractTranslationMessagesFile implements ITranslationMessagesFile { protected _filename : string ; protected _encoding : string ; protected _parsedDocument : Document ; protected _fileEndsWithEOL : boolean ; protected transUnits : ITransUnit [ ] ; protected _warnings : string [ ] ; protected _numberOfTransUnitsWithMissingId : number ; protected _numberOfUntranslatedTransUnits : number ; protected _numberOfReviewedTransUnits : number ; protected targetPraefix : string ; protected targetSuffix : string ; protected constructor ( ) { this . transUnits = null ; this . _warnings = [ ] ; } param xmlString param path param encoding param optionalMaster protected parseContent ( xmlString , path , encoding , optionalMaster ? ) { this . _filename = path ; this . _encoding = encoding ; this . _parsedDocument = new DOMParser ( ) . parseFromString ( xmlString , 'text/xml' ) ; this . _fileEndsWithEOL = xmlString . endsWith ( '\n' ) ; } abstract i18nFormat ( ) ; abstract fileType ( ) ; /**
     * return tag names of all elements that have mixed content.
     * These elements will not be beautified.
     * Typical candidates are source and target.
     */ protected abstract elementsWithMixedContent ( ) ; /**
     * Read all trans units from xml content.
     * Puts the found units into transUnits.
     * Puts warnings for missing ids.
     */ protected abstract initializeTransUnits ( ) ; protected lazyInitializeTransUnits ( ) { if ( isNullOrUndefined ( this . transUnits ) ) { this . initializeTransUnits ( ) ; this . countNumbers ( ) ; } } /**
     * count units after changes of trans units
     */ public countNumbers ( ) { this . _numberOfTransUnitsWithMissingId = 0 ; this . _numberOfUntranslatedTransUnits = 0 ; this . _numberOfReviewedTransUnits = 0 ; this . forEachTransUnit ( ( tu ) => { if ( isNullOrUndefined ( tu . id ) || tu . id === '' ) { this . _numberOfTransUnitsWithMissingId ++ ; } const state = tu . targetState ( ) ; if ( isNullOrUndefined ( state ) || state === STATE_NEW ) { this . _numberOfUntranslatedTransUnits ++ ; } if ( state === STATE_TRANSLATED ) { this . _numberOfReviewedTransUnits ++ ; } } ) ; } public warnings ( ) { this . lazyInitializeTransUnits ( ) ; return this . _warnings ; } /**
     * Total number of translation units found in the file.
     */ public numberOfTransUnits ( ) { this . lazyInitializeTransUnits ( ) ; return this . transUnits . length ; } /**
     * Number of translation units without translation found in the file.
     * These units have state 'translated'.
     */ numberOfUntranslatedTransUnits ( ) { this . lazyInitializeTransUnits ( ) ; return this . _numberOfUntranslatedTransUnits ; } /**
     * Number of translation units with state 'final'.
     */ numberOfReviewedTransUnits ( ) { this . lazyInitializeTransUnits ( ) ; return this . _numberOfReviewedTransUnits ; } /**
     * Number of translation units without translation found in the file.
     * These units have state 'translated'.
     */ public numberOfTransUnitsWithMissingId ( ) { this . lazyInitializeTransUnits ( ) ; return this . _numberOfTransUnitsWithMissingId ; } return abstract sourceLanguage ( ) ; return abstract targetLanguage ( ) ; param callback public forEachTransUnit ( callback ) { this . lazyInitializeTransUnits ( ) ; this . transUnits . forEach ( ( tu ) => callback ( tu ) ) ; } param id return public transUnitWithId ( id ) { this . lazyInitializeTransUnits ( ) ; return this . transUnits . find ( ( tu ) => tu . id === id ) ; } /**
     * Edit functions following her
     */ param language abstract setSourceLanguage ( language ) ; param language abstract setTargetLanguage ( language ) ; param targetPraefix public setNewTransUnitTargetPraefix ( targetPraefix ) { this . targetPraefix = targetPraefix ; } return getNewTransUnitTargetPraefix ( ) { return isNullOrUndefined ( this . targetPraefix ) ? '' : this . targetPraefix ; } param targetSuffix public setNewTransUnitTargetSuffix ( targetSuffix ) { this . targetSuffix = targetSuffix ; } return getNewTransUnitTargetSuffix ( ) { return isNullOrUndefined ( this . targetSuffix ) ? '' : this . targetSuffix ; } param foreignTransUnit param isDefaultLang param copyContent param importAfterElement return throws abstract importNewTransUnit ( foreignTransUnit , isDefaultLang , copyContent , importAfterElement ? ) ; param id public removeTransUnitWithId ( id ) { const tuNode = this . _parsedDocument . getElementById ( id ) ; if ( tuNode ) { tuNode . parentNode . removeChild ( tuNode ) ; this . lazyInitializeTransUnits ( ) ; this . transUnits = this . transUnits . filter ( ( tu ) => tu . id !== id ) ; this . countNumbers ( ) ; } } /**
     * The filename where the data is read from.
     */ public filename ( ) { return this . _filename ; } /**
     * The encoding if the xml content (UTF-8, ISO-8859-1, ...)
     */ public encoding ( ) { return this . _encoding ; } param beautifyOutput public editedContent ( beautifyOutput ? ) { const options = { } ; if ( beautifyOutput === true ) { options . beautify = true ; options . indentString = '  ' ; options . mixedContentElements = this . elementsWithMixedContent ( ) ; } const result = new XmlSerializer ( ) . serializeToString ( this . _parsedDocument , options ) ; if ( this . _fileEndsWithEOL ) { return result + '\n' ; } else { return result ; } } param lang param filename param isDefaultLang param copyContent abstract createTranslationFileForLang ( lang , filename , isDefaultLang , copyContent ) ; }