Skip to content

Commit 290a47d

Browse files
AndrewKushnirthePunderWoman
authored andcommitted
fix(core): handle missing withI18nSupport() call for components that use i18n blocks (#56175)
This commit updates hydration serialization logic to handle a case when the `withI18nSupport()` call is not present for an application that has a component that uses i18n blocks. Note: the issue is only reproducible for components that also inject `ViewContainerRef`, since it triggers a special serialization code path. Resolves #56074. PR Close #56175
1 parent 4cd5465 commit 290a47d

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

packages/core/src/hydration/annotate.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,14 @@ function annotateLContainerForHydration(lContainer: LContainer, context: Hydrati
182182
// Serialize the root component itself.
183183
const componentLViewNghIndex = annotateComponentLViewForHydration(componentLView, context);
184184

185+
if (componentLViewNghIndex === null) {
186+
// Component was not serialized (for example, if hydration was skipped by adding
187+
// the `ngSkipHydration` attribute or this component uses i18n blocks in the template,
188+
// but `withI18nSupport()` was not added), avoid annotating host element with the `ngh`
189+
// attribute.
190+
return;
191+
}
192+
185193
const hostElement = unwrapRNode(componentLView[HOST]!) as HTMLElement;
186194

187195
// Serialize all views within this view container.

packages/platform-server/test/hydration_spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,29 @@ describe('platform-server hydration integration', () => {
19641964
clearTranslations();
19651965
});
19661966

1967+
it('should append skip hydration flag if component uses i18n blocks and no `withI18nSupport()` call present', async () => {
1968+
@Component({
1969+
standalone: true,
1970+
selector: 'app',
1971+
template: '<div i18n>Hi!</div>',
1972+
})
1973+
class SimpleComponent {
1974+
// Having `ViewContainerRef` here is important: it triggers
1975+
// a code path that serializes top-level `LContainer`s.
1976+
vcr = inject(ViewContainerRef);
1977+
}
1978+
1979+
const hydrationFeatures = [] as unknown as HydrationFeature<any>[];
1980+
const html = await ssr(SimpleComponent, {hydrationFeatures});
1981+
1982+
const ssrContents = getAppContents(html);
1983+
1984+
// Since `withI18nSupport()` was not included and a component has i18n blocks -
1985+
// we expect that the `ngSkipHydration` attribute was added during serialization.
1986+
expect(ssrContents).not.toContain('ngh="');
1987+
expect(ssrContents).toContain('ngskiphydration="');
1988+
});
1989+
19671990
it('should not append skip hydration flag if component uses i18n blocks', async () => {
19681991
@Component({
19691992
standalone: true,

0 commit comments

Comments
 (0)