feat(compiler): do not parse xtb messages not needed by angular (#14111)
fixes #14046 PR Close #14111
This commit is contained in:
parent
20b454cbc9
commit
f7fba74c58
@ -29,10 +29,19 @@ export class Xtb extends Serializer {
|
|||||||
// xml nodes to i18n nodes
|
// xml nodes to i18n nodes
|
||||||
const i18nNodesByMsgId: {[msgId: string]: i18n.Node[]} = {};
|
const i18nNodesByMsgId: {[msgId: string]: i18n.Node[]} = {};
|
||||||
const converter = new XmlToI18n();
|
const converter = new XmlToI18n();
|
||||||
|
|
||||||
|
// Because we should be able to load xtb files that rely on features not supported by angular,
|
||||||
|
// we need to delay the conversion of html to i18n nodes so that non angular messages are not
|
||||||
|
// converted
|
||||||
Object.keys(mlNodesByMsgId).forEach(msgId => {
|
Object.keys(mlNodesByMsgId).forEach(msgId => {
|
||||||
const {i18nNodes, errors: e} = converter.convert(mlNodesByMsgId[msgId]);
|
const valueFn = function() {
|
||||||
errors.push(...e);
|
const {i18nNodes, errors} = converter.convert(mlNodesByMsgId[msgId]);
|
||||||
i18nNodesByMsgId[msgId] = i18nNodes;
|
if (errors.length) {
|
||||||
|
throw new Error(`xtb parse errors:\n${errors.join('\n')}`);
|
||||||
|
}
|
||||||
|
return i18nNodes;
|
||||||
|
};
|
||||||
|
createLazyProperty(i18nNodesByMsgId, msgId, valueFn);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
@ -49,6 +58,19 @@ export class Xtb extends Serializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createLazyProperty(messages: any, id: string, valueFn: () => any) {
|
||||||
|
Object.defineProperty(messages, id, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: function() {
|
||||||
|
const value = valueFn();
|
||||||
|
Object.defineProperty(messages, id, {enumerable: true, value});
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
set: _ => { throw new Error('Could not overwrite an XTB translation'); },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Extract messages as xml nodes from the xtb file
|
// Extract messages as xml nodes from the xtb file
|
||||||
class XtbParser implements ml.Visitor {
|
class XtbParser implements ml.Visitor {
|
||||||
private _bundleDepth: number;
|
private _bundleDepth: number;
|
||||||
|
@ -9,8 +9,10 @@
|
|||||||
import {escapeRegExp} from '@angular/core/src/facade/lang';
|
import {escapeRegExp} from '@angular/core/src/facade/lang';
|
||||||
|
|
||||||
import {serializeNodes} from '../../../src/i18n/digest';
|
import {serializeNodes} from '../../../src/i18n/digest';
|
||||||
|
import * as i18n from '../../../src/i18n/i18n_ast';
|
||||||
import {Xtb} from '../../../src/i18n/serializers/xtb';
|
import {Xtb} from '../../../src/i18n/serializers/xtb';
|
||||||
|
|
||||||
|
|
||||||
export function main(): void {
|
export function main(): void {
|
||||||
describe('XTB serializer', () => {
|
describe('XTB serializer', () => {
|
||||||
const serializer = new Xtb();
|
const serializer = new Xtb();
|
||||||
@ -100,6 +102,25 @@ export function main(): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('errors', () => {
|
describe('errors', () => {
|
||||||
|
it('should be able to parse non-angular xtb files without error', () => {
|
||||||
|
const XTB = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<translationbundle>
|
||||||
|
<translation id="angular">is great</translation>
|
||||||
|
<translation id="non angular">is <invalid>less</invalid> great</translation>
|
||||||
|
</translationbundle>`;
|
||||||
|
|
||||||
|
// Invalid messages should not cause the parser to throw
|
||||||
|
let i18nNodesByMsgId: {[id: string]: i18n.Node[]};
|
||||||
|
expect(() => { i18nNodesByMsgId = serializer.load(XTB, 'url'); }).not.toThrow();
|
||||||
|
|
||||||
|
expect(Object.keys(i18nNodesByMsgId).length).toEqual(2);
|
||||||
|
expect(serializeNodes(i18nNodesByMsgId['angular']).join('')).toEqual('is great');
|
||||||
|
// Messages that contain unsupported feature should throw on access
|
||||||
|
expect(() => {
|
||||||
|
const read = i18nNodesByMsgId['non angular'];
|
||||||
|
}).toThrowError(/xtb parse errors/);
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw on nested <translationbundle>', () => {
|
it('should throw on nested <translationbundle>', () => {
|
||||||
const XTB =
|
const XTB =
|
||||||
'<translationbundle><translationbundle></translationbundle></translationbundle>';
|
'<translationbundle><translationbundle></translationbundle></translationbundle>';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user