feat(compiler): add location note to extracted xliff2 files (#16791)
Add source location as a note tag as `<note category="location">path/to/file.ts:start_line[,end_line]</note>`. `[,end_line]` part is optional and specified only if the end line is different from the start line. Fixes #16531
This commit is contained in:
parent
85d4c4b82e
commit
08dfe91b95
|
@ -88,17 +88,25 @@ const EXPECTED_XLIFF2 = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<notes>
|
||||
<note category="description">desc</note>
|
||||
<note category="meaning">meaning</note>
|
||||
<note category="location">src/basic.ts:1</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>translate me</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="3492007542396725315">
|
||||
<notes>
|
||||
<note category="location">src/basic.ts:5</note>
|
||||
<note category="location">src/entry_components.ts:1</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>Welcome</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="126808141597411718">
|
||||
<notes>
|
||||
<note category="location">node_modules/third_party/other_comp.d.ts:1,2</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>other-3rdP-component
|
||||
multi-lines</source>
|
||||
|
|
|
@ -35,9 +35,9 @@ export class Xliff2 extends Serializer {
|
|||
|
||||
messages.forEach(message => {
|
||||
const unit = new xml.Tag(_UNIT_TAG, {id: message.id});
|
||||
const notes = new xml.Tag('notes');
|
||||
|
||||
if (message.description || message.meaning) {
|
||||
const notes = new xml.Tag('notes');
|
||||
if (message.description) {
|
||||
notes.children.push(
|
||||
new xml.CR(8),
|
||||
|
@ -49,11 +49,18 @@ export class Xliff2 extends Serializer {
|
|||
new xml.CR(8),
|
||||
new xml.Tag('note', {category: 'meaning'}, [new xml.Text(message.meaning)]));
|
||||
}
|
||||
|
||||
notes.children.push(new xml.CR(6));
|
||||
unit.children.push(new xml.CR(6), notes);
|
||||
}
|
||||
|
||||
message.sources.forEach((source: i18n.MessageSpan) => {
|
||||
notes.children.push(new xml.CR(8), new xml.Tag('note', {category: 'location'}, [
|
||||
new xml.Text(
|
||||
`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)
|
||||
]));
|
||||
});
|
||||
|
||||
notes.children.push(new xml.CR(6));
|
||||
unit.children.push(new xml.CR(6), notes);
|
||||
|
||||
const segment = new xml.Tag('segment');
|
||||
|
||||
segment.children.push(
|
||||
|
@ -367,4 +374,4 @@ function getTypeForTag(tag: string): string {
|
|||
default:
|
||||
return 'other';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,22 +24,33 @@ const HTML = `
|
|||
<p i18n="empty element">hello <span></span></p>
|
||||
<p i18n="@@baz">{ count, plural, =0 { { sex, select, other {<p>deeply nested</p>}} }}</p>
|
||||
<p i18n>{ count, plural, =0 { { sex, select, other {<p>deeply nested</p>}} }}</p>
|
||||
<p i18n>multi
|
||||
lines</p>
|
||||
`;
|
||||
|
||||
const WRITE_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xliff version="2.0" xmlns="urn:oasis:names:tc:xliff:document:2.0" srcLang="en">
|
||||
<file original="ng.template" id="ngi18n">
|
||||
<unit id="1933478729560469763">
|
||||
<notes>
|
||||
<note category="location">file.ts:2</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>translatable attribute</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="7056919470098446707">
|
||||
<notes>
|
||||
<note category="location">file.ts:3</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>translatable element <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">with placeholders</pc> <ph id="1" equiv="INTERPOLATION" disp="{{ interpolation}}"/></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2981514368455622387">
|
||||
<notes>
|
||||
<note category="location">file.ts:4</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">test</pc>} }</source>
|
||||
</segment>
|
||||
|
@ -48,6 +59,7 @@ const WRITE_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<notes>
|
||||
<note category="description">d</note>
|
||||
<note category="meaning">m</note>
|
||||
<note category="location">file.ts:5</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>foo</source>
|
||||
|
@ -56,6 +68,7 @@ const WRITE_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<unit id="6440235004920703622">
|
||||
<notes>
|
||||
<note category="description">nested</note>
|
||||
<note category="location">file.ts:6</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>"><pc id="1" equivStart="START_UNDERLINED_TEXT" equivEnd="CLOSE_UNDERLINED_TEXT" type="fmt" dispStart="<u>" dispEnd="</u>"><ph id="2" equiv="INTERPOLATION" disp="{{interpolation}}"/> Text</pc></pc></source>
|
||||
|
@ -64,6 +77,7 @@ const WRITE_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<unit id="8779402634269838862">
|
||||
<notes>
|
||||
<note category="description">ph names</note>
|
||||
<note category="location">file.ts:7</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><ph id="0" equiv="LINE_BREAK" type="fmt" disp="<br/>"/><ph id="1" equiv="TAG_IMG" type="image" disp="<img/>"/><ph id="2" equiv="TAG_IMG_1" type="image" disp="<img/>"/></source>
|
||||
|
@ -72,21 +86,37 @@ const WRITE_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<unit id="6536355551500405293">
|
||||
<notes>
|
||||
<note category="description">empty element</note>
|
||||
<note category="location">file.ts:8</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>hello <pc id="0" equivStart="START_TAG_SPAN" equivEnd="CLOSE_TAG_SPAN" type="other" dispStart="<span>" dispEnd="</span>"></pc></source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="baz">
|
||||
<notes>
|
||||
<note category="location">file.ts:9</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">deeply nested</pc>} } } }</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2015957479576096115">
|
||||
<notes>
|
||||
<note category="location">file.ts:10</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">deeply nested</pc>} } } }</source>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2340165783990709777">
|
||||
<notes>
|
||||
<note category="location">file.ts:11,12</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>multi
|
||||
lines</source>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
`;
|
||||
|
@ -95,18 +125,27 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<xliff version="2.0" xmlns="urn:oasis:names:tc:xliff:document:2.0" srcLang="en" trgLang="fr">
|
||||
<file original="ng.template" id="ngi18n">
|
||||
<unit id="1933478729560469763">
|
||||
<notes>
|
||||
<note category="location">file.ts:2</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>translatable attribute</source>
|
||||
<target>etubirtta elbatalsnart</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="7056919470098446707">
|
||||
<notes>
|
||||
<note category="location">file.ts:3</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>translatable element <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">with placeholders</pc> <ph id="1" equiv="INTERPOLATION" disp="{{ interpolation}}"/></source>
|
||||
<target><ph id="1" equiv="INTERPOLATION" disp="{{ interpolation}}"/> <pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>">sredlohecalp htiw</pc> tnemele elbatalsnart</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2981514368455622387">
|
||||
<notes>
|
||||
<note category="location">file.ts:4</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">test</pc>} }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">TEST</pc>} }</target>
|
||||
|
@ -116,6 +155,7 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<notes>
|
||||
<note category="description">d</note>
|
||||
<note category="meaning">m</note>
|
||||
<note category="location">file.ts:5</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>foo</source>
|
||||
|
@ -125,6 +165,7 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<unit id="6440235004920703622">
|
||||
<notes>
|
||||
<note category="description">nested</note>
|
||||
<note category="location">file.ts:6</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><pc id="0" equivStart="START_BOLD_TEXT" equivEnd="CLOSE_BOLD_TEXT" type="fmt" dispStart="<b>" dispEnd="</b>"><pc id="1" equivStart="START_UNDERLINED_TEXT" equivEnd="CLOSE_UNDERLINED_TEXT" type="fmt" dispStart="<u>" dispEnd="</u>"><ph id="2" equiv="INTERPOLATION" disp="{{interpolation}}"/> Text</pc></pc></source>
|
||||
|
@ -134,6 +175,7 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<unit id="8779402634269838862">
|
||||
<notes>
|
||||
<note category="description">ph names</note>
|
||||
<note category="location">file.ts:7</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source><ph id="0" equiv="LINE_BREAK" type="fmt" disp="<br/>"/><ph id="1" equiv="TAG_IMG" type="image" disp="<img/>"/><ph id="2" equiv="TAG_IMG_1" type="image" disp="<img/>"/></source>
|
||||
|
@ -143,6 +185,7 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<unit id="6536355551500405293">
|
||||
<notes>
|
||||
<note category="description">empty element</note>
|
||||
<note category="location">file.ts:8</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>hello <pc id="0" equivStart="START_TAG_SPAN" equivEnd="CLOSE_TAG_SPAN" type="other" dispStart="<span>" dispEnd="</span>"></pc></source>
|
||||
|
@ -150,17 +193,34 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
</segment>
|
||||
</unit>
|
||||
<unit id="baz">
|
||||
<notes>
|
||||
<note category="location">file.ts:9</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">deeply nested</pc>} } } }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">profondément imbriqué</pc>} } } }</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2015957479576096115">
|
||||
<notes>
|
||||
<note category="location">file.ts:10</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">deeply nested</pc>} } } }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<pc id="0" equivStart="START_PARAGRAPH" equivEnd="CLOSE_PARAGRAPH" type="other" dispStart="<p>" dispEnd="</p>">profondément imbriqué</pc>} } } }</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="2340165783990709777">
|
||||
<notes>
|
||||
<note category="location">file.ts:11,12</note>
|
||||
</notes>
|
||||
<segment>
|
||||
<source>multi
|
||||
lines</source>
|
||||
<target>multi
|
||||
lignes</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
`;
|
||||
|
@ -170,7 +230,7 @@ export function main(): void {
|
|||
|
||||
function toXliff(html: string, locale: string | null = null): string {
|
||||
const catalog = new MessageBundle(new HtmlParser, [], {}, locale);
|
||||
catalog.updateFromTemplate(html, '', DEFAULT_INTERPOLATION_CONFIG);
|
||||
catalog.updateFromTemplate(html, 'file.ts', DEFAULT_INTERPOLATION_CONFIG);
|
||||
return catalog.write(serializer);
|
||||
}
|
||||
|
||||
|
@ -208,8 +268,10 @@ export function main(): void {
|
|||
'6536355551500405293': '<ph name="START_TAG_SPAN"/><ph name="CLOSE_TAG_SPAN"/> olleh',
|
||||
'baz':
|
||||
'{VAR_PLURAL, plural, =0 {[{VAR_SELECT, select, other {[<ph name="START_PARAGRAPH"/>, profondément imbriqué, <ph name="CLOSE_PARAGRAPH"/>]}}, ]}}',
|
||||
'2015957479576096115':
|
||||
'{VAR_PLURAL, plural, =0 {[{VAR_SELECT, select, other {[<ph name="START_PARAGRAPH"/>, profondément imbriqué, <ph name="CLOSE_PARAGRAPH"/>]}}, ]}}'
|
||||
'2015957479576096115': '{VAR_PLURAL, plural, =0 {[{VAR_SELECT, select, other {[<ph' +
|
||||
' name="START_PARAGRAPH"/>, profondément imbriqué, <ph name="CLOSE_PARAGRAPH"/>]}}, ]}}',
|
||||
'2340165783990709777': `multi
|
||||
lignes`
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -333,4 +395,4 @@ export function main(): void {
|
|||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ const HTML = `
|
|||
<p i18n="ph names"><br><img><div></div></p>
|
||||
<p i18n="@@baz">{ count, plural, =0 { { sex, select, other {<p>deeply nested</p>}} }}</p>
|
||||
<p i18n>{ count, plural, =0 { { sex, select, other {<p>deeply nested</p>}} }}</p>
|
||||
<p i18n>multi
|
||||
lines</p>
|
||||
`;
|
||||
|
||||
const WRITE_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
@ -112,6 +114,15 @@ const WRITE_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<context context-type="linenumber">11</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="fcfa109b0e152d4c217dbc02530be0bcb8123ad1" datatype="html">
|
||||
<source>multi
|
||||
lines</source>
|
||||
<target/>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">12</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -195,6 +206,16 @@ const LOAD_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<source>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<x id="START_PARAGRAPH" ctype="x-p"/>deeply nested<x id="CLOSE_PARAGRAPH" ctype="x-p"/>} } } }</source>
|
||||
<target>{VAR_PLURAL, plural, =0 {{VAR_SELECT, select, other {<x id="START_PARAGRAPH" ctype="x-p"/>profondément imbriqué<x id="CLOSE_PARAGRAPH" ctype="x-p"/>} } } }</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="fcfa109b0e152d4c217dbc02530be0bcb8123ad1" datatype="html">
|
||||
<source>multi
|
||||
lines</source>
|
||||
<target>multi
|
||||
lignes</target>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">file.ts</context>
|
||||
<context context-type="linenumber">12</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -243,7 +264,10 @@ export function main(): void {
|
|||
'baz':
|
||||
'{VAR_PLURAL, plural, =0 {[{VAR_SELECT, select, other {[<ph name="START_PARAGRAPH"/>, profondément imbriqué, <ph name="CLOSE_PARAGRAPH"/>]}}, ]}}',
|
||||
'0e16a673a5a7a135c9f7b957ec2c5c6f6ee6e2c4':
|
||||
'{VAR_PLURAL, plural, =0 {[{VAR_SELECT, select, other {[<ph name="START_PARAGRAPH"/>, profondément imbriqué, <ph name="CLOSE_PARAGRAPH"/>]}}, ]}}'
|
||||
'{VAR_PLURAL, plural, =0 {[{VAR_SELECT, select, other {[<ph' +
|
||||
' name="START_PARAGRAPH"/>, profondément imbriqué, <ph name="CLOSE_PARAGRAPH"/>]}}, ]}}',
|
||||
'fcfa109b0e152d4c217dbc02530be0bcb8123ad1': `multi
|
||||
lignes`
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue