import { format } from 'util' ; import { ITranslationMessagesFile } from '../api/i-translation-messages-file' ; import { ITransUnit } from '../api/i-trans-unit' ; import { FORMAT_XLIFF20 , FILETYPE_XLIFF20 } from '../api/constants' ; import { DOMUtilities } from './dom-utilities' ; import { Xliff2TransUnit } from './xliff2-trans-unit' ; import { AbstractTranslationMessagesFile } from './abstract-translation-messages-file' ; import { AbstractTransUnit } from './abstract-trans-unit' ; /**
 * Created by martin on 04.05.2017.
 * An XLIFF 2.0 file read from a source file.
 * Format definition is: http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/xliff-core-v2.0-os.html
 *
 * Defines some relevant get and set method for reading and modifying such a file.
 */ export class Xliff2File extends AbstractTranslationMessagesFile implements ITranslationMessagesFile { param xmlString param path param encoding return constructor ( xmlString , path , encoding ) { super ( ) ; this . _warnings = [ ] ; this . _numberOfTransUnitsWithMissingId = 0 ; this . initializeFromContent ( xmlString , path , encoding ) ; } private initializeFromContent ( xmlString , path , encoding ) { this . parseContent ( xmlString , path , encoding ) ; const xliffList = this . _parsedDocument . getElementsByTagName ( 'xliff' ) ; if ( xliffList . length !== 1 ) { throw new Error ( format ( 'File "%s" seems to be no xliff file (should contain an xliff element)' , path ) ) ; } else { const version = xliffList . item ( 0 ) . getAttribute ( 'version' ) ; const expectedVersion = '2.0' ; if ( version !== expectedVersion ) { throw new Error ( format ( 'File "%s" seems to be no xliff 2 file, version should be %s, found %s' , path , expectedVersion , version ) ) ; } } return this ; } /**
     * File format as it is used in config files.
     * Currently 'xlf', 'xmb', 'xmb2'
     * Returns one of the constants FORMAT_..
     */ public i18nFormat ( ) { return FORMAT_XLIFF20 ; } /**
     * File type.
     * Here 'XLIFF 2.0'
     */ public fileType ( ) { return FILETYPE_XLIFF20 ; } /**
     * return tag names of all elements that have mixed content.
     * These elements will not be beautified.
     * Typical candidates are source and target.
     */ protected elementsWithMixedContent ( ) { return [ 'skeleton' , 'note' , 'data' , 'source' , 'target' , 'pc' , 'mrk' ] ; } protected initializeTransUnits ( ) { this . transUnits = [ ] ; const transUnitsInFile = this . _parsedDocument . getElementsByTagName ( 'unit' ) ; for ( let i = 0 ; i < transUnitsInFile . length ; i ++ ) { const transunit = transUnitsInFile . item ( i ) ; const id = transunit . getAttribute ( 'id' ) ; if ( ! id ) { this . _warnings . push ( format ( 'oops, trans-unit without "id" found in master, please check file %s' , this . _filename ) ) ; } this . transUnits . push ( new Xliff2TransUnit ( transunit , id , this ) ) ; } } return public sourceLanguage ( ) { const xliffElem = DOMUtilities . getFirstElementByTagName ( this . _parsedDocument , 'xliff' ) ; if ( xliffElem ) { return xliffElem . getAttribute ( 'srcLang' ) ; } else { return null ; } } param language public setSourceLanguage ( language ) { const xliffElem = DOMUtilities . getFirstElementByTagName ( this . _parsedDocument , 'xliff' ) ; if ( xliffElem ) { xliffElem . setAttribute ( 'srcLang' , language ) ; } } return public targetLanguage ( ) { const xliffElem = DOMUtilities . getFirstElementByTagName ( this . _parsedDocument , 'xliff' ) ; if ( xliffElem ) { return xliffElem . getAttribute ( 'trgLang' ) ; } else { return null ; } } param language public setTargetLanguage ( language ) { const xliffElem = DOMUtilities . getFirstElementByTagName ( this . _parsedDocument , 'xliff' ) ; if ( xliffElem ) { xliffElem . setAttribute ( 'trgLang' , language ) ; } } param foreignTransUnit param isDefaultLang param copyContent param importAfterElement return throws importNewTransUnit ( foreignTransUnit , isDefaultLang , copyContent , importAfterElement ? ) { if ( this . transUnitWithId ( foreignTransUnit . id ) ) { throw new Error ( format ( 'tu with id %s already exists in file, cannot import it' , foreignTransUnit . id ) ) ; } const newTu = ( < AbstractTransUnit > foreignTransUnit ) . cloneWithSourceAsTarget ( isDefaultLang , copyContent , this ) ; const fileElement = DOMUtilities . getFirstElementByTagName ( this . _parsedDocument , 'file' ) ; if ( ! fileElement ) { throw new Error ( format ( 'File "%s" seems to be no xliff 2.0 file (should contain a file element)' , this . _filename ) ) ; } let inserted = false ; let isAfterElementPartOfFile = false ; if ( ! ! importAfterElement ) { const insertionPoint = this . transUnitWithId ( importAfterElement . id ) ; if ( ! ! insertionPoint ) { isAfterElementPartOfFile = true ; } } if ( importAfterElement === undefined || ( importAfterElement && ! isAfterElementPartOfFile ) ) { fileElement . appendChild ( newTu . asXmlElement ( ) ) ; inserted = true ; } else if ( importAfterElement === null ) { const firstUnitElement = DOMUtilities . getFirstElementByTagName ( this . _parsedDocument , 'unit' ) ; if ( firstUnitElement ) { DOMUtilities . insertBefore ( newTu . asXmlElement ( ) , firstUnitElement ) ; inserted = true ; } else { fileElement . appendChild ( newTu . asXmlElement ( ) ) ; inserted = true ; } } else { const refUnitElement = DOMUtilities . getElementByTagNameAndId ( this . _parsedDocument , 'unit' , importAfterElement . id ) ; if ( refUnitElement ) { DOMUtilities . insertAfter ( newTu . asXmlElement ( ) , refUnitElement ) ; inserted = true ; } } if ( inserted ) { this . lazyInitializeTransUnits ( ) ; this . transUnits . push ( newTu ) ; this . countNumbers ( ) ; return newTu ; } else { return null ; } } param lang param filename param isDefaultLang param copyContent public createTranslationFileForLang ( lang , filename , isDefaultLang , copyContent ) { const translationFile = new Xliff2File ( this . editedContent ( ) , filename , this . encoding ( ) ) ; translationFile . setNewTransUnitTargetPraefix ( this . targetPraefix ) ; translationFile . setNewTransUnitTargetSuffix ( this . targetSuffix ) ; translationFile . setTargetLanguage ( lang ) ; translationFile . forEachTransUnit ( ( transUnit ) => { ( < AbstractTransUnit > transUnit ) . useSourceAsTarget ( isDefaultLang , copyContent ) ; } ) ; return translationFile ; } }