ngx-i18nsupport-lib
Version:
A Typescript library to work with Angular generated i18n files (xliff, xmb)
392 lines • 17.6 kB
JavaScript
"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 xliff2_message_parser_1 = require("./xliff2-message-parser");
var util_1 = require("util");
/**
* Created by martin on 04.05.2017.
* A Translation Unit in an XLIFF 2.0 file.
*/
var Xliff2TransUnit = /** @class */ (function (_super) {
__extends(Xliff2TransUnit, _super);
function Xliff2TransUnit(_element, _id, _translationMessagesFile) {
return _super.call(this, _element, _id, _translationMessagesFile) || this;
}
Xliff2TransUnit.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.
*/
Xliff2TransUnit.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..
var segment = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'segment');
source = segment.parentNode.appendChild(this._element.ownerDocument.createElement('source'));
}
dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(source, newContent);
};
/**
* Return a parser used for normalized messages.
*/
Xliff2TransUnit.prototype.messageParser = function () {
return new xliff2_message_parser_1.Xliff2MessageParser();
};
/**
* The original text value, that is to be translated, as normalized message.
*/
Xliff2TransUnit.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).
*/
Xliff2TransUnit.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.
*/
Xliff2TransUnit.prototype.targetContentNormalized = function () {
var targetElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'target');
return new xliff2_message_parser_1.Xliff2MessageParser().createNormalizedMessageFromXML(targetElement, this.sourceContentNormalized());
};
/**
* State of the translation as stored in the xml.
*/
Xliff2TransUnit.prototype.nativeTargetState = function () {
var segmentElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'segment');
if (segmentElement) {
return segmentElement.getAttribute('state');
}
else {
return null;
}
};
/**
* set state in xml.
* @param nativeState
*/
Xliff2TransUnit.prototype.setNativeTargetState = function (nativeState) {
var segmentElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'segment');
if (segmentElement) {
segmentElement.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.
*/
Xliff2TransUnit.prototype.mapStateToNativeState = function (state) {
switch (state) {
case api_1.STATE_NEW:
return 'initial';
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
*/
Xliff2TransUnit.prototype.mapNativeStateToState = function (nativeState) {
switch (nativeState) {
case 'initial':
return api_1.STATE_NEW;
case 'translated':
return api_1.STATE_TRANSLATED;
case 'reviewed': // same as translated
return api_1.STATE_TRANSLATED;
case 'final':
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.
*/
Xliff2TransUnit.prototype.sourceReferences = function () {
// Source is found as <file>:<line> in <note category="location">...
var noteElements = this._element.getElementsByTagName('note');
var sourceRefs = [];
for (var i = 0; i < noteElements.length; i++) {
var noteElem = noteElements.item(i);
if (noteElem.getAttribute('category') === 'location') {
var sourceAndPos = dom_utilities_1.DOMUtilities.getPCDATA(noteElem);
sourceRefs.push(this.parseSourceAndPos(sourceAndPos));
}
}
return sourceRefs;
};
/**
* Parses something like 'c:\xxx:7' and returns source and linenumber.
* @param sourceAndPos something like 'c:\xxx:7', last colon is the separator
* @return {{sourcefile: string, linenumber: number}}
*/
Xliff2TransUnit.prototype.parseSourceAndPos = function (sourceAndPos) {
var index = sourceAndPos.lastIndexOf(':');
if (index < 0) {
return {
sourcefile: sourceAndPos,
linenumber: 0
};
}
else {
return {
sourcefile: sourceAndPos.substring(0, index),
linenumber: this.parseLineNumber(sourceAndPos.substring(index + 1))
};
}
};
Xliff2TransUnit.prototype.parseLineNumber = function (lineNumberString) {
return Number.parseInt(lineNumberString);
};
/**
* 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.
*/
Xliff2TransUnit.prototype.setSourceReferences = function (sourceRefs) {
var _this = this;
this.removeAllSourceReferences();
var notesElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'notes');
if (sourceRefs.length === 0 && !util_1.isNullOrUndefined(notesElement) && notesElement.childNodes.length === 0) {
// remove empty notes element
notesElement.parentNode.removeChild(notesElement);
return;
}
if (util_1.isNullOrUndefined(notesElement)) {
notesElement = this._element.ownerDocument.createElement('notes');
this._element.insertBefore(notesElement, this._element.childNodes.item(0));
}
sourceRefs.forEach(function (ref) {
var note = _this._element.ownerDocument.createElement('note');
note.setAttribute('category', 'location');
note.appendChild(_this._element.ownerDocument.createTextNode(ref.sourcefile + ':' + ref.linenumber.toString(10)));
notesElement.appendChild(note);
});
};
Xliff2TransUnit.prototype.removeAllSourceReferences = function () {
var noteElements = this._element.getElementsByTagName('note');
var toBeRemoved = [];
for (var i = 0; i < noteElements.length; i++) {
var elem = noteElements.item(i);
if (elem.getAttribute('category') === '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 2.0 this is stored as a note element with attribute category="description".
*/
Xliff2TransUnit.prototype.description = function () {
var noteElem = this.findNoteElementWithCategoryAttribute('description');
if (noteElem) {
return dom_utilities_1.DOMUtilities.getPCDATA(noteElem);
}
else {
return null;
}
};
/**
* Change description property of trans-unit.
* @param {string} description
*/
Xliff2TransUnit.prototype.setDescription = function (description) {
var noteElem = this.findNoteElementWithCategoryAttribute('description');
if (description) {
if (util_1.isNullOrUndefined(noteElem)) {
// create it
noteElem = this.createNoteElementWithCategoryAttribute('description');
}
dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(noteElem, description);
}
else {
if (!util_1.isNullOrUndefined(noteElem)) {
// remove node
this.removeNoteElementWithCategoryAttribute('description');
}
}
};
/**
* Find a note element with attribute from='<attrValue>'
* @param {string} attrValue
* @return {Element} element or null is absent
*/
Xliff2TransUnit.prototype.findNoteElementWithCategoryAttribute = function (attrValue) {
var noteElements = this._element.getElementsByTagName('note');
for (var i = 0; i < noteElements.length; i++) {
var noteElem = noteElements.item(i);
if (noteElem.getAttribute('category') === attrValue) {
return noteElem;
}
}
return null;
};
/**
* Create a new note element with attribute from='<attrValue>'
* @param {string} attrValue
* @return the new created element
*/
Xliff2TransUnit.prototype.createNoteElementWithCategoryAttribute = function (attrValue) {
var notesElement = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'notes');
if (util_1.isNullOrUndefined(notesElement)) {
// create it
notesElement = this._element.ownerDocument.createElement('notes');
this._element.appendChild(notesElement);
}
var noteElement = this._element.ownerDocument.createElement('note');
noteElement.setAttribute('category', attrValue);
notesElement.appendChild(noteElement);
return noteElement;
};
/**
* Remove note element with attribute from='<attrValue>'
* @param {string} attrValue
*/
Xliff2TransUnit.prototype.removeNoteElementWithCategoryAttribute = function (attrValue) {
var noteElement = this.findNoteElementWithCategoryAttribute(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 2.0 this is stored as a note element with attribute category="meaning".
*/
Xliff2TransUnit.prototype.meaning = function () {
var noteElem = this.findNoteElementWithCategoryAttribute('meaning');
if (noteElem) {
return dom_utilities_1.DOMUtilities.getPCDATA(noteElem);
}
else {
return null;
}
};
/**
* Change meaning property of trans-unit.
* @param {string} meaning
*/
Xliff2TransUnit.prototype.setMeaning = function (meaning) {
var noteElem = this.findNoteElementWithCategoryAttribute('meaning');
if (meaning) {
if (util_1.isNullOrUndefined(noteElem)) {
// create it
noteElem = this.createNoteElementWithCategoryAttribute('meaning');
}
dom_utilities_1.DOMUtilities.replaceContentWithXMLContent(noteElem, meaning);
}
else {
if (!util_1.isNullOrUndefined(noteElem)) {
// remove node
this.removeNoteElementWithCategoryAttribute('meaning');
}
}
};
/**
* Set the translation to a given string (including markup).
* @param translation
*/
Xliff2TransUnit.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 = source.parentNode.appendChild(this._element.ownerDocument.createElement('target'));
}
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)
*/
Xliff2TransUnit.prototype.cloneWithSourceAsTarget = function (isDefaultLang, copyContent, targetFile) {
var element = this._element.cloneNode(true);
var clone = new Xliff2TransUnit(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)
*/
Xliff2TransUnit.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 = source.parentNode.appendChild(this._element.ownerDocument.createElement('target'));
}
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, '');
}
var segment = dom_utilities_1.DOMUtilities.getFirstElementByTagName(this._element, 'segment');
if (segment) {
if (isDefaultLang) {
segment.setAttribute('state', this.mapStateToNativeState(api_1.STATE_FINAL));
}
else {
segment.setAttribute('state', this.mapStateToNativeState(api_1.STATE_NEW));
}
}
};
return Xliff2TransUnit;
}(abstract_trans_unit_1.AbstractTransUnit));
exports.Xliff2TransUnit = Xliff2TransUnit;
//# sourceMappingURL=S:/experimente/ngx-i18nsupport-lib/src/impl/xliff2-trans-unit.js.map