UNPKG

ngx-i18nsupport-lib

Version:

A Typescript library to work with Angular generated i18n files (xliff, xmb)

379 lines 17 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var api_1 = require("../api"); var dom_utilities_1 = require("./dom-utilities"); var abstract_trans_unit_1 = require("./abstract-trans-unit"); var xliff_message_parser_1 = require("./xliff-message-parser"); var util_1 = require("util"); /** * Created by martin on 01.05.2017. * A Translation Unit in an XLIFF 1.2 file. */ var XliffTransUnit = /** @class */ (function (_super) { __extends(XliffTransUnit, _super); function XliffTransUnit(_element, _id, _translationMessagesFile) { return _super.call(this, _element, _id, _translationMessagesFile) || this; } XliffTransUnit.prototype.sourceContent = function () { var sourceElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'source'); return dom_utilities_1.DOMUtilities.getXMLContent(sourceElement); }; /** * Set new source content in the transunit. * Normally, this is done by ng-extract. * Method only exists to allow xliffmerge to merge missing changed source content. * @param newContent the new content. */ XliffTransUnit.prototype.setSourceContent = function (newContent) { var source = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'source'); if (!source) { // should not happen, there always has to be a source, but who knows.. source = this._element.appendChild(this._element.ownerDocument.createElement('source')); } dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(source, newContent); }; /** * Return a parser used for normalized messages. */ XliffTransUnit.prototype.messageParser = function () { return new xliff_message_parser_1.XliffMessageParser(); }; /** * The original text value, that is to be translated, as normalized message. */ XliffTransUnit.prototype.createSourceContentNormalized = function () { var sourceElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'source'); if (sourceElement) { return this.messageParser().createNormalizedMessageFromXML(sourceElement, null); } else { return null; } }; /** * the translated value (containing all markup, depends on the concrete format used). */ XliffTransUnit.prototype.targetContent = function () { var targetElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'target'); return dom_utilities_1.DOMUtilities.getXMLContent(targetElement); }; /** * the translated value, but all placeholders are replaced with {{n}} (starting at 0) * and all embedded html is replaced by direct html markup. */ XliffTransUnit.prototype.targetContentNormalized = function () { var targetElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'target'); return new xliff_message_parser_1.XliffMessageParser().createNormalizedMessageFromXML(targetElement, this.sourceContentNormalized()); }; /** * State of the translation as stored in the xml. */ XliffTransUnit.prototype.nativeTargetState = function () { var targetElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'target'); if (targetElement) { return targetElement.getAttribute('state'); } else { return null; } }; /** * set state in xml. * @param nativeState */ XliffTransUnit.prototype.setNativeTargetState = function (nativeState) { var targetElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'target'); if (targetElement) { targetElement.setAttribute('state', nativeState); } }; /** * Map an abstract state (new, translated, final) to a concrete state used in the xml. * Returns the state to be used in the xml. * @param state one of Constants.STATE... * @returns a native state (depends on concrete format) * @throws error, if state is invalid. */ XliffTransUnit.prototype.mapStateToNativeState = function (state) { switch (state) { case api_1.STATE_NEW: return 'new'; case api_1.STATE_TRANSLATED: return 'translated'; case api_1.STATE_FINAL: return 'final'; default: throw new Error('unknown state ' + state); } }; /** * Map a native state (found in the document) to an abstract state (new, translated, final). * Returns the abstract state. * @param nativeState */ XliffTransUnit.prototype.mapNativeStateToState = function (nativeState) { switch (nativeState) { case 'new': return api_1.STATE_NEW; case 'needs-translation': return api_1.STATE_NEW; case 'translated': return api_1.STATE_TRANSLATED; case 'needs-adaptation': return api_1.STATE_TRANSLATED; case 'needs-l10n': return api_1.STATE_TRANSLATED; case 'needs-review-adaptation': return api_1.STATE_TRANSLATED; case 'needs-review-l10n': return api_1.STATE_TRANSLATED; case 'needs-review-translation': return api_1.STATE_TRANSLATED; case 'final': return api_1.STATE_FINAL; case 'signed-off': return api_1.STATE_FINAL; default: return api_1.STATE_NEW; } }; /** * All the source elements in the trans unit. * The source element is a reference to the original template. * It contains the name of the template file and a line number with the position inside the template. * It is just a help for translators to find the context for the translation. * This is set when using Angular 4.0 or greater. * Otherwise it just returns an empty array. */ XliffTransUnit.prototype.sourceReferences = function () { var sourceElements = this._element.getElementsByTagName('context-group'); var sourceRefs = []; for (var i = 0; i < sourceElements.length; i++) { var elem = sourceElements.item(i); if (elem.getAttribute('purpose') === 'location') { var contextElements = elem.getElementsByTagName('context'); var sourcefile = null; var linenumber = 0; for (var j = 0; j < contextElements.length; j++) { var contextElem = contextElements.item(j); if (contextElem.getAttribute('context-type') === 'sourcefile') { sourcefile = dom_utilities_1.DOMUtilities.getPCDATA(contextElem); } if (contextElem.getAttribute('context-type') === 'linenumber') { linenumber = Number.parseInt(dom_utilities_1.DOMUtilities.getPCDATA(contextElem)); } } sourceRefs.push({ sourcefile: sourcefile, linenumber: linenumber }); } } return sourceRefs; }; /** * Set source ref elements in the transunit. * Normally, this is done by ng-extract. * Method only exists to allow xliffmerge to merge missing source refs. * @param sourceRefs the sourcerefs to set. Old ones are removed. */ XliffTransUnit.prototype.setSourceReferences = function (sourceRefs) { var _this = this; this.removeAllSourceReferences(); sourceRefs.forEach(function (ref) { var contextGroup = _this._element.ownerDocument.createElement('context-group'); contextGroup.setAttribute('purpose', 'location'); var contextSource = _this._element.ownerDocument.createElement('context'); contextSource.setAttribute('context-type', 'sourcefile'); contextSource.appendChild(_this._element.ownerDocument.createTextNode(ref.sourcefile)); var contextLine = _this._element.ownerDocument.createElement('context'); contextLine.setAttribute('context-type', 'linenumber'); contextLine.appendChild(_this._element.ownerDocument.createTextNode(ref.linenumber.toString(10))); contextGroup.appendChild(contextSource); contextGroup.appendChild(contextLine); _this._element.appendChild(contextGroup); }); }; XliffTransUnit.prototype.removeAllSourceReferences = function () { var sourceElements = this._element.getElementsByTagName('context-group'); var toBeRemoved = []; for (var i = 0; i < sourceElements.length; i++) { var elem = sourceElements.item(i); if (elem.getAttribute('purpose') === 'location') { toBeRemoved.push(elem); } } toBeRemoved.forEach(function (elem) { elem.parentNode.removeChild(elem); }); }; /** * The description set in the template as value of the i18n-attribute. * e.g. i18n="mydescription". * In xliff this is stored as a note element with attribute from="description". */ XliffTransUnit.prototype.description = function () { var noteElem = this.findNoteElementWithFromAttribute('description'); if (noteElem) { return dom_utilities_1.DOMUtilities.getPCDATA(noteElem); } else { return null; } }; /** * Change description property of trans-unit. * @param {string} description */ XliffTransUnit.prototype.setDescription = function (description) { var noteElem = this.findNoteElementWithFromAttribute('description'); if (description) { if (util_1.isNullOrUndefined(noteElem)) { // create it noteElem = this.createNoteElementWithFromAttribute('description'); } dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(noteElem, description); } else { if (!util_1.isNullOrUndefined(noteElem)) { // remove node this.removeNoteElementWithFromAttribute('description'); } } }; /** * Find a note element with attribute from='<attrValue>' * @param {string} attrValue * @return {Element} element or null is absent */ XliffTransUnit.prototype.findNoteElementWithFromAttribute = function (attrValue) { var noteElements = this._element.getElementsByTagName('note'); for (var i = 0; i < noteElements.length; i++) { var noteElem = noteElements.item(i); if (noteElem.getAttribute('from') === attrValue) { return noteElem; } } return null; }; /** * Create a new note element with attribute from='<attrValue>' * @param {string} attrValue * @return the new created element */ XliffTransUnit.prototype.createNoteElementWithFromAttribute = function (attrValue) { var noteElement = this._element.ownerDocument.createElement('note'); noteElement.setAttribute('from', attrValue); noteElement.setAttribute('priority', '1'); this._element.appendChild(noteElement); return noteElement; }; /** * Remove note element with attribute from='<attrValue>' * @param {string} attrValue */ XliffTransUnit.prototype.removeNoteElementWithFromAttribute = function (attrValue) { var noteElement = this.findNoteElementWithFromAttribute(attrValue); if (noteElement) { this._element.removeChild(noteElement); } }; /** * The meaning (intent) set in the template as value of the i18n-attribute. * This is the part in front of the | symbol. * e.g. i18n="meaning|mydescription". * In xliff this is stored as a note element with attribute from="meaning". */ XliffTransUnit.prototype.meaning = function () { var noteElem = this.findNoteElementWithFromAttribute('meaning'); if (noteElem) { return dom_utilities_1.DOMUtilities.getPCDATA(noteElem); } else { return null; } }; /** * Change meaning property of trans-unit. * @param {string} meaning */ XliffTransUnit.prototype.setMeaning = function (meaning) { var noteElem = this.findNoteElementWithFromAttribute('meaning'); if (meaning) { if (util_1.isNullOrUndefined(noteElem)) { // create it noteElem = this.createNoteElementWithFromAttribute('meaning'); } dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(noteElem, meaning); } else { if (!util_1.isNullOrUndefined(noteElem)) { // remove node this.removeNoteElementWithFromAttribute('meaning'); } } }; /** * Set the translation to a given string (including markup). * @param translation */ XliffTransUnit.prototype.translateNative = function (translation) { var target = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'target'); if (!target) { var source = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'source'); target = dom_utilities_1.DOMUtilities.createFollowingSibling('target', source); } dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(target, translation); this.setTargetState(api_1.STATE_TRANSLATED); }; /** * Copy source to target to use it as dummy translation. * Returns a changed copy of this trans unit. * receiver is not changed. * (internal usage only, a client should call importNewTransUnit on ITranslationMessageFile) */ XliffTransUnit.prototype.cloneWithSourceAsTarget = function (isDefaultLang, copyContent, targetFile) { var element = this._element.cloneNode(true); var clone = new XliffTransUnit(element, this._id, targetFile); clone.useSourceAsTarget(isDefaultLang, copyContent); return clone; }; /** * Copy source to target to use it as dummy translation. * (internal usage only, a client should call createTranslationFileForLang on ITranslationMessageFile) */ XliffTransUnit.prototype.useSourceAsTarget = function (isDefaultLang, copyContent) { var source = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'source'); var target = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'target'); if (!target) { target = dom_utilities_1.DOMUtilities.createFollowingSibling('target', source); } if (isDefaultLang || copyContent) { var sourceString = dom_utilities_1.DOMUtilities.getXMLContent(source); var newTargetString = sourceString; if (!this.isICUMessage(sourceString)) { newTargetString = this.translationMessagesFile().getNewTransUnitTargetPraefix() + sourceString + this.translationMessagesFile().getNewTransUnitTargetSuffix(); } dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(target, newTargetString); } else { dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(target, ''); } if (isDefaultLang) { target.setAttribute('state', this.mapStateToNativeState(api_1.STATE_FINAL)); } else { target.setAttribute('state', this.mapStateToNativeState(api_1.STATE_NEW)); } }; return XliffTransUnit; }(abstract_trans_unit_1.AbstractTransUnit)); exports.XliffTransUnit = XliffTransUnit; //# sourceMappingURL=S:/experimente/ngx-i18nsupport-lib/src/impl/xliff-trans-unit.js.map