diff --git a/packages/core/src/render3/i18n.ts b/packages/core/src/render3/i18n.ts index e04c076d80..a76f72c7eb 100644 --- a/packages/core/src/render3/i18n.ts +++ b/packages/core/src/render3/i18n.ts @@ -958,9 +958,7 @@ export function ɵɵi18n(index: number, message: string, subTemplateIndex?: numb export function ɵɵi18nAttributes(index: number, values: string[]): void { const tView = getLView()[TVIEW]; ngDevMode && assertDefined(tView, `tView should be defined`); - if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) { - i18nAttributesFirstPass(tView, index, values); - } + i18nAttributesFirstPass(tView, index, values); } /** @@ -985,8 +983,10 @@ function i18nAttributesFirstPass(tView: TView, index: number, values: string[]) // Even indexes are text (including bindings) const hasBinding = !!value.match(BINDING_REGEXP); if (hasBinding) { - addAllToArray( - generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes); + if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) { + addAllToArray( + generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes); + } } else { const lView = getLView(); elementAttributeInternal(previousElementIndex, attrName, value, lView); @@ -1001,7 +1001,9 @@ function i18nAttributesFirstPass(tView: TView, index: number, values: string[]) } } - tView.data[index + HEADER_OFFSET] = updateOpCodes; + if (tView.firstTemplatePass && tView.data[index + HEADER_OFFSET] === null) { + tView.data[index + HEADER_OFFSET] = updateOpCodes; + } } let changeMask = 0b0; diff --git a/packages/core/test/acceptance/i18n_spec.ts b/packages/core/test/acceptance/i18n_spec.ts index 81e56ac043..e1a8b742ba 100644 --- a/packages/core/test/acceptance/i18n_spec.ts +++ b/packages/core/test/acceptance/i18n_spec.ts @@ -715,6 +715,42 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => { const element = fixture.nativeElement.firstChild; expect(element.title).toBe('Bonjour Angular'); }); + + it('should apply i18n attributes during second template pass', () => { + @Directive({ + selector: '[test]', + inputs: ['test'], + exportAs: 'dir', + }) + class Dir { + } + + @Component({ + selector: 'other', + template: `
` + }) + class Other { + } + + @Component({ + selector: 'blah', + template: ` + + + ` + }) + class Cmp { + } + + TestBed.configureTestingModule({ + declarations: [Dir, Cmp, Other], + }); + + const fixture = TestBed.createComponent(Cmp); + fixture.detectChanges(); + expect(fixture.debugElement.children[0].children[0].references.ref.test).toBe('Set'); + expect(fixture.debugElement.children[1].children[0].references.ref.test).toBe('Set'); + }); }); it('should work with directives and host bindings', () => {