angular-t9n
Version:
A translation tool for Angular i18n
102 lines (87 loc) • 3.58 kB
text/typescript
import { Injectable } from '@nestjs/common';
import { TranslationSourceUnit, TranslationTargetUnit } from '../models';
import { XlfDeserializerBase } from './xlf-deserializer-base';
import { XmlParser } from './xml-parser';
()
export class Xlf2Deserializer extends XlfDeserializerBase {
constructor(parser: XmlParser) {
super(parser);
}
deserializeSource(content: string) {
const doc = this._createDocument(content);
const language = doc.documentElement.getAttribute('srcLang')!;
const fileNode = this._getFileNode(doc);
const unitMap = Array.from(fileNode.childNodes)
.filter((c) => c.nodeName === 'unit')
.map((u) => this._deserializeSourceUnit(u as Element))
.reduce(
(current, next) => current.set(next.id, next),
new Map<string, TranslationSourceUnit>(),
);
return { language, unitMap };
}
deserializeTarget(content: string) {
const doc = this._createDocument(content);
const language = doc.documentElement.getAttribute('trgLang')!;
this._assertTargetLanguage(language);
const fileNode = this._getFileNode(doc);
const unitMap = Array.from(fileNode.childNodes)
.filter((c) => c.nodeName === 'unit')
.map((u) => this._deserializeTargetUnit(u as Element))
.reduce(
(current, next) => current.set(next.id, next),
new Map<string, TranslationTargetUnit>(),
);
return { language, unitMap };
}
protected _assertXliff(doc: Document) {
super._assertXliff(doc);
if (doc.documentElement.getAttribute('version') !== '2.0') {
throw new Error(
`Expected the xliff tag to have a version attribute with value '2.0' (<xliff version="2.0" ...)`,
);
} else if (!doc.documentElement.getAttribute('srcLang')) {
throw new Error(
`Expected the xliff tag to have a srcLang attribute (e.g. <xliff srcLang="en" ...)`,
);
}
}
private _deserializeTargetUnit(unit: Element): TranslationTargetUnit {
const segment = unit.getElementsByTagName('segment')[0];
return {
...this._deserializeSourceUnit(unit),
target: this._extractTarget(segment),
state: this._extractState(segment),
};
}
private _deserializeSourceUnit(unitElement: Element): TranslationSourceUnit {
const unit: TranslationSourceUnit = {
id: unitElement.getAttribute('id')!,
source: this._extractSource(unitElement.getElementsByTagName('segment')[0]),
};
const notesElement = unitElement.getElementsByTagName('notes')[0];
if (!notesElement) {
return unit;
}
unit.description = this._extractNote(notesElement, 'description')[0];
unit.meaning = this._extractNote(notesElement, 'meaning')[0];
const locations = this._extractNote(notesElement, 'location');
unit.locations = locations.length ? locations : undefined;
return unit;
}
private _extractSource(segment: Element) {
return this._convertToString(segment.getElementsByTagName('source')[0]);
}
private _extractTarget(segment: Element) {
return this._convertToString(segment.getElementsByTagName('target')[0]);
}
private _extractNote(notes: Element, category: string): string[] {
return Array.from(notes.getElementsByTagName('note'))
.filter((n) => n.getAttribute('category') === category && n.textContent)
.map((n) => n.textContent!);
}
private _extractState(segment: Element) {
const state = segment.getAttribute('state');
return state === 'translated' || state === 'reviewed' || state === 'final' ? state : 'initial';
}
}