@ngx-i18nsupport/ngx-i18nsupport-lib
Version:
A Typescript library to work with Angular generated i18n files (xliff, xmb)
288 lines (250 loc) • 10.1 kB
text/typescript
import {STATE_TRANSLATED, ITranslationMessagesFile, INormalizedMessage, ITransUnit, INote} from './internalapi';
import {AbstractTranslationMessagesFile} from './abstract-translation-messages-file';
import {isNullOrUndefined, isString} from 'util';
import {ParsedMessage} from './parsed-message';
import {AbstractMessageParser} from './abstract-message-parser';
/**
* Created by roobm on 10.05.2017.
* Abstract superclass for all implementations of ITransUnit.
*/
export abstract class AbstractTransUnit implements ITransUnit {
private _sourceContentNormalized: ParsedMessage;
protected constructor(protected _element: Element,
protected _id: string,
protected _translationMessagesFile: ITranslationMessagesFile) {
}
public get id(): string {
return this._id;
}
/**
* The file the unit belongs to.,
*/
translationMessagesFile(): ITranslationMessagesFile {
return this._translationMessagesFile;
}
/**
* The original text value, that is to be translated.
* Contains all markup, depends on the concrete format used.
*/
abstract sourceContent(): string;
/**
* Test, wether setting of source content is supported.
* If not, setSourceContent in trans-unit will do nothing.
* xtb does not support this, all other formats do.
*/
supportsSetSourceContent(): boolean {
return true;
}
/**
* 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.
*/
abstract setSourceContent(newContent: string);
/**
* The original text value, that is to be translated, as normalized message.
*/
public sourceContentNormalized(): ParsedMessage {
if (isNullOrUndefined(this._sourceContentNormalized)) {
this._sourceContentNormalized = this.createSourceContentNormalized();
}
return this._sourceContentNormalized;
}
/**
* The original text value, that is to be translated, as normalized message.
*/
abstract createSourceContentNormalized(): ParsedMessage;
/**
* The translated value.
* Contains all markup, depends on the concrete format used.
*/
abstract targetContent(): string;
/**
* The translated value as normalized message.
* All placeholders are replaced with {{n}} (starting at 0)
* and all embedded html is replaced by direct html markup.
*/
abstract targetContentNormalized(): INormalizedMessage;
/**
* State of the translation as stored in the xml.
*/
abstract nativeTargetState(): string;
/**
* State of the translation.
* (on of new, translated, final)
* Return values are defined as Constants STATE_...
*/
public targetState(): string {
const nativeState = this.nativeTargetState();
return this.mapNativeStateToState(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.
*/
protected abstract mapStateToNativeState(state: string): string;
/**
* Map a native state (found in the document) to an abstract state (new, translated, final).
* Returns the abstract state.
* @param nativeState nativeState
*/
protected abstract mapNativeStateToState(nativeState: string): string;
/**
* set state in xml.
* @param nativeState nativeState
*/
protected abstract setNativeTargetState(nativeState: string);
/**
* Modify the target state.
* @param newState one of the 3 allowed target states new, translated, final.
* Constants STATE_...
* Invalid states throw an error.
*/
setTargetState(newState: string) {
this.setNativeTargetState(this.mapStateToNativeState(newState));
if (this.translationMessagesFile() instanceof AbstractTranslationMessagesFile) {
(<AbstractTranslationMessagesFile> this.translationMessagesFile()).countNumbers();
}
}
/**
* 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.
*/
abstract sourceReferences(): {sourcefile: string, linenumber: number}[];
/**
* Test, wether setting of source refs is supported.
* If not, setSourceReferences will do nothing.
* xtb does not support this, all other formats do.
*/
public supportsSetSourceReferences(): boolean {
return true;
}
/**
* 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.
*/
abstract setSourceReferences(sourceRefs: {sourcefile: string, linenumber: number}[]);
/**
* The description set in the template as value of the i18n-attribute.
* e.g. i18n="mydescription".
*/
abstract description(): string;
/**
* 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".
*/
abstract meaning(): string;
/**
* Test, wether setting of description and meaning is supported.
* If not, setDescription and setMeaning will do nothing.
* xtb does not support this, all other formats do.
*/
public supportsSetDescriptionAndMeaning(): boolean {
return true;
}
/**
* Change description property of trans-unit.
* @param description description
*/
abstract setDescription(description: string);
/**
* Change meaning property of trans-unit.
* @param meaning meaning
*/
abstract setMeaning(meaning: string);
/**
* Get all notes of the trans-unit.
* Notes are remarks made by a translator.
* (description and meaning are not included here!)
*/
abstract notes(): INote[];
/**
* Test, wether setting of notes is supported.
* If not, setNotes will do nothing.
* xtb does not support this, all other formats do.
*/
abstract supportsSetNotes(): boolean;
/**
* Add notes to trans unit.
* @param newNotes the notes to add.
* @throws an Error if any note contains descpription or meaning as from attribute.
*/
abstract setNotes(newNotes: INote[]);
/**
* Check notes
* @param newNotes the notes to add.
* @throws an Error if any note contains description or meaning as from attribute.
*/
protected checkNotes(newNotes: INote[]) {
// check from values
const errorInFromNote = newNotes.find((note) => note.from === 'description' || note.from === 'meaning');
if (!isNullOrUndefined(errorInFromNote)) {
throw new Error('description or meaning are not allowed as from atttribute');
}
}
/**
* The real xml element used for the trans unit.
* (internal usage only, a client should never need this)
* @return real xml element used for the trans unit.
*/
public asXmlElement(): Element {
return this._element;
}
/**
* 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)
*/
abstract cloneWithSourceAsTarget(isDefaultLang: boolean, copyContent: boolean, targetFile: ITranslationMessagesFile): AbstractTransUnit;
/**
* Copy source to target to use it as dummy translation.
* (internal usage only, a client should call createTranslationFileForLang on ITranslationMessageFile)
*/
abstract useSourceAsTarget(isDefaultLang: boolean, copyContent: boolean);
/**
* Translate the trans unit.
* @param translation the translated string or (preferred) a normalized message.
* The pure string can contain any markup and will not be checked.
* So it can damage the document.
* A normalized message prevents this.
*/
public translate(translation: string | INormalizedMessage) {
let translationNative: string;
if (isString(translation)) {
translationNative = <string> translation;
} else {
translationNative = (<INormalizedMessage> translation).asNativeString();
}
this.translateNative(translationNative);
this.setTargetState(STATE_TRANSLATED);
}
/**
* Return a parser used for normalized messages.
*/
protected abstract messageParser(): AbstractMessageParser;
/**
* Test, wether message looks like ICU message.
* @param message message
* @return wether message looks like ICU message.
*/
public isICUMessage(message: string): boolean {
return this.messageParser().isICUMessageStart(message);
}
/**
* Set the translation to a given string (including markup).
* @param translation translation
*/
protected abstract translateNative(translation: string);
}