fix(compiler): allow empty translations for attributes (#14085)
fixes #13897
This commit is contained in:
parent
3ef73c2b19
commit
05b2b49711
|
@ -327,6 +327,7 @@ class _Visitor implements html.Visitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates the given message given the `TranslationBundle`
|
// Translates the given message given the `TranslationBundle`
|
||||||
|
// This is used for translating elements / blocks - see `_translateAttributes` for attributes
|
||||||
// no-op when called in extraction mode (returns [])
|
// no-op when called in extraction mode (returns [])
|
||||||
private _translateMessage(el: html.Node, message: i18n.Message): html.Node[] {
|
private _translateMessage(el: html.Node, message: i18n.Message): html.Node[] {
|
||||||
if (message && this._mode === _VisitorMode.Merge) {
|
if (message && this._mode === _VisitorMode.Merge) {
|
||||||
|
@ -368,7 +369,9 @@ class _Visitor implements html.Visitor {
|
||||||
const message: i18n.Message = this._createI18nMessage([attr], meaning, '', '');
|
const message: i18n.Message = this._createI18nMessage([attr], meaning, '', '');
|
||||||
const nodes = this._translations.get(message);
|
const nodes = this._translations.get(message);
|
||||||
if (nodes) {
|
if (nodes) {
|
||||||
if (nodes[0] instanceof html.Text) {
|
if (nodes.length == 0) {
|
||||||
|
translatedAttributes.push(new html.Attribute(attr.name, '', attr.sourceSpan));
|
||||||
|
} else if (nodes[0] instanceof html.Text) {
|
||||||
const value = (nodes[0] as html.Text).value;
|
const value = (nodes[0] as html.Text).value;
|
||||||
translatedAttributes.push(new html.Attribute(attr.name, value, attr.sourceSpan));
|
translatedAttributes.push(new html.Attribute(attr.name, value, attr.sourceSpan));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -383,6 +383,24 @@ export function main() {
|
||||||
const HTML = `<div>before<p i18n="m|d">foo</p><!-- comment --></div>`;
|
const HTML = `<div>before<p i18n="m|d">foo</p><!-- comment --></div>`;
|
||||||
expect(fakeTranslate(HTML)).toEqual('<div>before<p>**foo**</p></div>');
|
expect(fakeTranslate(HTML)).toEqual('<div>before<p>**foo**</p></div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should merge empty messages', () => {
|
||||||
|
const HTML = `<div i18n>some element</div>`;
|
||||||
|
const htmlNodes: html.Node[] = parseHtml(HTML);
|
||||||
|
const messages: i18n.Message[] =
|
||||||
|
extractMessages(htmlNodes, DEFAULT_INTERPOLATION_CONFIG, [], {}).messages;
|
||||||
|
|
||||||
|
expect(messages.length).toEqual(1);
|
||||||
|
const i18nMsgMap: {[id: string]: i18n.Node[]} = {};
|
||||||
|
i18nMsgMap[digest(messages[0])] = [];
|
||||||
|
const translations = new TranslationBundle(i18nMsgMap, digest);
|
||||||
|
|
||||||
|
const output =
|
||||||
|
mergeTranslations(htmlNodes, translations, DEFAULT_INTERPOLATION_CONFIG, [], {});
|
||||||
|
expect(output.errors).toEqual([]);
|
||||||
|
|
||||||
|
expect(serializeHtmlNodes(output.rootNodes).join('')).toEqual(`<div></div>`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('blocks', () => {
|
describe('blocks', () => {
|
||||||
|
@ -422,6 +440,25 @@ export function main() {
|
||||||
const HTML = `<p i18n-title="m|d" title=""></p>`;
|
const HTML = `<p i18n-title="m|d" title=""></p>`;
|
||||||
expect(fakeTranslate(HTML)).toEqual('<p title=""></p>');
|
expect(fakeTranslate(HTML)).toEqual('<p title=""></p>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should merge empty attributes', () => {
|
||||||
|
const HTML = `<div i18n-title title="some attribute">some element</div>`;
|
||||||
|
const htmlNodes: html.Node[] = parseHtml(HTML);
|
||||||
|
const messages: i18n.Message[] =
|
||||||
|
extractMessages(htmlNodes, DEFAULT_INTERPOLATION_CONFIG, [], {}).messages;
|
||||||
|
|
||||||
|
expect(messages.length).toEqual(1);
|
||||||
|
const i18nMsgMap: {[id: string]: i18n.Node[]} = {};
|
||||||
|
i18nMsgMap[digest(messages[0])] = [];
|
||||||
|
const translations = new TranslationBundle(i18nMsgMap, digest);
|
||||||
|
|
||||||
|
const output =
|
||||||
|
mergeTranslations(htmlNodes, translations, DEFAULT_INTERPOLATION_CONFIG, [], {});
|
||||||
|
expect(output.errors).toEqual([]);
|
||||||
|
|
||||||
|
expect(serializeHtmlNodes(output.rootNodes).join(''))
|
||||||
|
.toEqual(`<div title="">some element</div>`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -453,12 +490,11 @@ function fakeTranslate(
|
||||||
|
|
||||||
const translations = new TranslationBundle(i18nMsgMap, digest);
|
const translations = new TranslationBundle(i18nMsgMap, digest);
|
||||||
|
|
||||||
const translatedNodes =
|
const output = mergeTranslations(
|
||||||
mergeTranslations(
|
htmlNodes, translations, DEFAULT_INTERPOLATION_CONFIG, implicitTags, implicitAttrs);
|
||||||
htmlNodes, translations, DEFAULT_INTERPOLATION_CONFIG, implicitTags, implicitAttrs)
|
expect(output.errors).toEqual([]);
|
||||||
.rootNodes;
|
|
||||||
|
|
||||||
return serializeHtmlNodes(translatedNodes).join('');
|
return serializeHtmlNodes(output.rootNodes).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function extract(
|
function extract(
|
||||||
|
|
|
@ -94,6 +94,11 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<target><x id="START_TAG_DIV" ctype="x-div"/><x id="CLOSE_TAG_DIV" ctype="x-div"/><x id="TAG_IMG" ctype="image"/><x id="LINE_BREAK" ctype="lb"/></target>
|
<target><x id="START_TAG_DIV" ctype="x-div"/><x id="CLOSE_TAG_DIV" ctype="x-div"/><x id="TAG_IMG" ctype="image"/><x id="LINE_BREAK" ctype="lb"/></target>
|
||||||
<note priority="1" from="description">ph names</note>
|
<note priority="1" from="description">ph names</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="empty target" datatype="html">
|
||||||
|
<source><x id="LINE_BREAK" ctype="lb"/><x id="TAG_IMG" ctype="image"/><x id="START_TAG_DIV" ctype="x-div"/><x id="CLOSE_TAG_DIV" ctype="x-div"/></source>
|
||||||
|
<target/>
|
||||||
|
<note priority="1" from="description">ph names</note>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
@ -110,6 +115,7 @@ export function main(): void {
|
||||||
|
|
||||||
function loadAsMap(xliff: string): {[id: string]: string} {
|
function loadAsMap(xliff: string): {[id: string]: string} {
|
||||||
const i18nNodesByMsgId = serializer.load(xliff, 'url');
|
const i18nNodesByMsgId = serializer.load(xliff, 'url');
|
||||||
|
|
||||||
const msgMap: {[id: string]: string} = {};
|
const msgMap: {[id: string]: string} = {};
|
||||||
Object.keys(i18nNodesByMsgId)
|
Object.keys(i18nNodesByMsgId)
|
||||||
.forEach(id => msgMap[id] = serializeNodes(i18nNodesByMsgId[id]).join(''));
|
.forEach(id => msgMap[id] = serializeNodes(i18nNodesByMsgId[id]).join(''));
|
||||||
|
@ -133,6 +139,7 @@ export function main(): void {
|
||||||
'bar': 'tata',
|
'bar': 'tata',
|
||||||
'd7fa2d59aaedcaa5309f13028c59af8c85b8c49d':
|
'd7fa2d59aaedcaa5309f13028c59af8c85b8c49d':
|
||||||
'<ph name="START_TAG_DIV"/><ph name="CLOSE_TAG_DIV"/><ph name="TAG_IMG"/><ph name="LINE_BREAK"/>',
|
'<ph name="START_TAG_DIV"/><ph name="CLOSE_TAG_DIV"/><ph name="TAG_IMG"/><ph name="LINE_BREAK"/>',
|
||||||
|
'empty target': '',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue