From 9a81f0d9a82a47df8c82d091e7b31118612b1566 Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Tue, 15 Jan 2019 12:10:41 -0800 Subject: [PATCH] fix(ivy): update i18n/i18nStart and i18nAttributes instruction order (#28163) Prior to this change element's i18n attributes like "i18n-title" were processed after "i18n" ones that placed "i18n" and "i18nAttributes" instructions in wrong order, thus "i18nAttributes" failed to target its host element at runtime. This change updates processing order and puts "i18nAttributes" instructions in front of "i18n" ones to resolve the problem. PR Close #28163 --- .../compliance/r3_view_compiler_i18n_spec.ts | 4 ++-- .../compiler/src/render3/view/template.ts | 10 ++++++---- packages/core/test/i18n_integration_spec.ts | 19 +++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts index 6ee98313b1..ccf6bb2eef 100644 --- a/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts @@ -580,8 +580,8 @@ describe('i18n support in the view compiler', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div"); - $r3$.ɵi18n(1, $MSG_EXTERNAL_4969674997806975147$$APP_SPEC_TS_0$); - $r3$.ɵi18nAttributes(2, $_c0$); + $r3$.ɵi18nAttributes(1, $_c0$); + $r3$.ɵi18n(2, $MSG_EXTERNAL_4969674997806975147$$APP_SPEC_TS_0$); $r3$.ɵelementEnd(); } } diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index 7058630ada..4f1f1762bf 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -619,10 +619,6 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver this.creationInstruction(element.sourceSpan, R3.disableBindings); } - if (isI18nRootElement) { - this.i18nStart(element.sourceSpan, element.i18n !, createSelfClosingI18nInstruction); - } - // process i18n element attributes if (i18nAttrs.length) { let hasBindings: boolean = false; @@ -656,6 +652,12 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver } } + // Note: it's important to keep i18n/i18nStart instructions after i18nAttributes ones, + // to make sure i18nAttributes instruction targets current element at runtime. + if (isI18nRootElement) { + this.i18nStart(element.sourceSpan, element.i18n !, createSelfClosingI18nInstruction); + } + // The style bindings code is placed into two distinct blocks within the template function AOT // code: creation and update. The creation code contains the `elementStyling` instructions // which will apply the collected binding values to the element. `elementStyling` is diff --git a/packages/core/test/i18n_integration_spec.ts b/packages/core/test/i18n_integration_spec.ts index e4d2f3bbf0..6463305be2 100644 --- a/packages/core/test/i18n_integration_spec.ts +++ b/packages/core/test/i18n_integration_spec.ts @@ -117,19 +117,18 @@ onlyInIvy('Ivy i18n logic').describe('i18n', function() { } }); - fixmeIvy('FW-904: i18n attributes placed on i18n root node don\'t work') - .it('should work correctly when placed on i18n root node', () => { - const title = 'Hello {{ name }}'; - const content = 'Hello'; - const template = ` + it('should work correctly when placed on i18n root node', () => { + const title = 'Hello {{ name }}'; + const content = 'Hello'; + const template = `
${content}
`; - const fixture = getFixtureWithOverrides({template}); + const fixture = getFixtureWithOverrides({template}); - const element = fixture.nativeElement.firstChild; - expect(element.title).toBe('Bonjour John'); - expect(element).toHaveText('Bonjour'); - }); + const element = fixture.nativeElement.firstChild; + expect(element.title).toBe('Bonjour John'); + expect(element).toHaveText('Bonjour'); + }); it('should add i18n attributes on self-closing tags', () => { const title = 'Hello {{ name }}';