Sitelet https://github.com/angular/angular/commit/63f9e16
Skip to content

Commit 63f9e16

Browse files
petebacondarwinmhevery
authored andcommitted
fix(compiler): ensure that i18n message-parts have the correct source-span (#39486)
In an i18n message, two placeholders next to each other must have an "empty" message-part to separate them. Previously, the source-span for this message-part was pointing to the wrong original location. This caused problems in the generated source-maps and lead to extracted i18n messages from being rendered incorrectly. PR Close #39486
1 parent d34e36c commit 63f9e16

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

‎packages/compiler/src/render3/view/i18n/localize_utils.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ function processMessagePieces(pieces: o.MessagePiece[]):
120120
placeHolders.push(part);
121121
if (pieces[i - 1] instanceof o.PlaceholderPiece) {
122122
// There were two placeholders in a row, so we need to add an empty message part.
123-
messageParts.push(createEmptyMessagePart(part.sourceSpan.end));
123+
messageParts.push(createEmptyMessagePart(pieces[i - 1].sourceSpan.end));
124124
}
125125
}
126126
}

‎packages/compiler/test/render3/view/i18n_spec.ts‎

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -489,14 +489,33 @@ describe('serializeI18nMessageForLocalize', () => {
489489
expect(placeHolders[3].sourceSpan.toString()).toEqual('</span>');
490490
});
491491

492+
it('should create the correct source-spans when there are two placeholders next to each other',
493+
() => {
494+
const {messageParts, placeHolders} = serialize('<b>{{value}}</b>');
495+
expect(messageParts[0].text).toEqual('');
496+
expect(humanizeSourceSpan(messageParts[0].sourceSpan)).toEqual('"" (10-10)');
497+
expect(messageParts[1].text).toEqual('');
498+
expect(humanizeSourceSpan(messageParts[1].sourceSpan)).toEqual('"" (13-13)');
499+
expect(messageParts[2].text).toEqual('');
500+
expect(humanizeSourceSpan(messageParts[2].sourceSpan)).toEqual('"" (22-22)');
501+
expect(messageParts[3].text).toEqual('');
502+
expect(humanizeSourceSpan(messageParts[3].sourceSpan)).toEqual('"" (26-26)');
503+
504+
expect(placeHolders[0].text).toEqual('START_BOLD_TEXT');
505+
expect(humanizeSourceSpan(placeHolders[0].sourceSpan)).toEqual('"<b>" (10-13)');
506+
expect(placeHolders[1].text).toEqual('INTERPOLATION');
507+
expect(humanizeSourceSpan(placeHolders[1].sourceSpan)).toEqual('"{{value}}" (13-22)');
508+
expect(placeHolders[2].text).toEqual('CLOSE_BOLD_TEXT');
509+
expect(humanizeSourceSpan(placeHolders[2].sourceSpan)).toEqual('"</b>" (22-26)');
510+
});
511+
492512
it('should serialize simple ICU for `$localize()`', () => {
493513
expect(serialize('{age, plural, 10 {ten} other {other}}')).toEqual({
494514
messageParts: [literal('{VAR_PLURAL, plural, 10 {ten} other {other}}')],
495515
placeHolders: []
496516
});
497517
});
498518

499-
500519
it('should serialize nested ICUs for `$localize()`', () => {
501520
expect(serialize(
502521
'{age, plural, 10 {ten {size, select, 1 {one} 2 {two} other {2+}}} other {other}}'))
@@ -509,7 +528,6 @@ describe('serializeI18nMessageForLocalize', () => {
509528
});
510529
});
511530

512-
513531
it('should serialize ICU with embedded HTML for `$localize()`', () => {
514532
expect(serialize('{age, plural, 10 {<b>ten</b>} other {<div class="A">other</div>}}')).toEqual({
515533
messageParts: [
@@ -594,4 +612,8 @@ function literal(text: string, span: any = jasmine.any(ParseSourceSpan)): o.Lite
594612

595613
function placeholder(name: string, span: any = jasmine.any(ParseSourceSpan)): o.PlaceholderPiece {
596614
return new o.PlaceholderPiece(name, span);
597-
}
615+
}
616+
617+
function humanizeSourceSpan(span: ParseSourceSpan): string {
618+
return `"${span.toString()}" (${span.start.offset}-${span.end.offset})`;
619+
}

0 commit comments

Comments
 (0)