From 7e64bbe5a82f1d1ac3c23cb166aa381cae751015 Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Tue, 15 Oct 2019 15:54:14 -0700 Subject: [PATCH] fix(ivy): use container i18n meta if a message is a single ICU (#33191) Prior to this commit, metadata defined on ICU container element was not inherited by the ICU if the whole message is a single ICU (for example: `{count, select, ...}). This commit updates the logic to use parent container i18n meta information for the cases when a message consists of a single ICU. Fixes #33171 PR Close #33191 --- .../compliance/r3_view_compiler_i18n_spec.ts | 24 +++++++++++++++++++ .../compiler/src/render3/view/i18n/meta.ts | 8 ++++--- packages/core/test/acceptance/i18n_spec.ts | 20 ++++++++++++++++ 3 files changed, 49 insertions(+), 3 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 40bef90382..063fe67d78 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 @@ -3385,6 +3385,30 @@ describe('i18n support in the template compiler', () => { verify(input, output); }); + + it('should attach metadata in case an ICU represents the whole message', () => { + const input = ` +
{count, select, 1 {one} other {more than one}}
+ `; + + const output = String.raw ` + var $I18N_0$; + if (ngI18nClosureMode) { + /** + * @desc descA + * @meaning meaningA + */ + const $MSG_EXTERNAL_idA$$APP_SPEC_TS_1$ = goog.getMsg("{VAR_SELECT, select, 1 {one} other {more than one}}"); + $I18N_0$ = $MSG_EXTERNAL_idA$$APP_SPEC_TS_1$; + } + else { + $I18N_0$ = $localize \`:meaningA|descA@@idA:{VAR_SELECT, select, 1 {one} other {more than one}}\`; + } + $I18N_0$ = i0.ɵɵi18nPostprocess($I18N_0$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); + `; + + verify(input, output); + }); }); describe('errors', () => { diff --git a/packages/compiler/src/render3/view/i18n/meta.ts b/packages/compiler/src/render3/view/i18n/meta.ts index afee55bade..313a83e69e 100644 --- a/packages/compiler/src/render3/view/i18n/meta.ts +++ b/packages/compiler/src/render3/view/i18n/meta.ts @@ -111,7 +111,7 @@ export class I18nMetaVisitor implements html.Visitor { element.attrs = attrs; } } - html.visitAll(this, element.children); + html.visitAll(this, element.children, element.i18n); return element; } @@ -127,8 +127,10 @@ export class I18nMetaVisitor implements html.Visitor { const icu = icuFromI18nMessage(message); icu.name = name; } else { - // when ICU is a root level translation - message = this._generateI18nMessage([expansion], meta); + // ICU is a top level message, try to use metadata from container element if provided via + // `context` argument. Note: context may not be available for standalone ICUs (without + // wrapping element), so fallback to ICU metadata in this case. + message = this._generateI18nMessage([expansion], context || meta); } expansion.i18n = message; return expansion; diff --git a/packages/core/test/acceptance/i18n_spec.ts b/packages/core/test/acceptance/i18n_spec.ts index 58469b704e..344384e022 100644 --- a/packages/core/test/acceptance/i18n_spec.ts +++ b/packages/core/test/acceptance/i18n_spec.ts @@ -1031,6 +1031,26 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => { expect(fixture.debugElement.nativeElement.innerHTML).toContain('A'); expect(fixture.debugElement.nativeElement.innerHTML).toContain('B'); }); + + it('should use metadata from container element if a message is a single ICU', () => { + loadTranslations({idA: '{VAR_SELECT, select, 1 {un} other {plus d\'un}}'}); + + @Component({ + selector: 'app', + template: ` +
{count, select, 1 {one} other {more than one}}
+ ` + }) + class AppComponent { + count = 2; + } + + TestBed.configureTestingModule({declarations: [AppComponent]}); + + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.innerHTML).toContain('plus d\'un'); + }); }); describe('should support attributes', () => {