Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ivy): use container i18n meta if a message is a single ICU #33191

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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 = `
<div i18n="meaningA|descA@@idA">{count, select, 1 {one} other {more than one}}</div>
`;

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', () => {
Expand Down
8 changes: 5 additions & 3 deletions packages/compiler/src/render3/view/i18n/meta.ts
Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down
20 changes: 20 additions & 0 deletions packages/core/test/acceptance/i18n_spec.ts
Expand Up @@ -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: `
<div i18n="@@idA">{count, select, 1 {one} other {more than one}}</div>
`
})
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', () => {
Expand Down