Skip to content

Commit 5d76d84

Browse files
committed
fix(@angular/ssr): improve locale handling in app-engine
Refactor app-engine to correctly handle single locale configurations and update manifest type definitions. Add new test cases for localized apps with a single locale. closes #31675 (cherry picked from commit 30efc56)
1 parent 515b09c commit 5d76d84

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

packages/angular/ssr/src/app-engine.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,10 @@ export class AngularAppEngine {
191191
* @returns A promise that resolves to the entry point exports or `undefined` if not found.
192192
*/
193193
private getEntryPointExportsForUrl(url: URL): Promise<EntryPointExports> | undefined {
194-
const { basePath } = this.manifest;
194+
const { basePath, supportedLocales } = this.manifest;
195+
195196
if (this.supportedLocales.length === 1) {
196-
return this.getEntryPointExports('');
197+
return this.getEntryPointExports(supportedLocales[this.supportedLocales[0]]);
197198
}
198199

199200
const potentialLocale = getPotentialLocaleIdFromUrl(url, basePath);

packages/angular/ssr/src/manifest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export interface AngularAppEngineManifest {
7373
* - `key`: The locale identifier (e.g., 'en', 'fr').
7474
* - `value`: The url segment associated with that locale.
7575
*/
76-
readonly supportedLocales: Readonly<Record<string, string | undefined>>;
76+
readonly supportedLocales: Readonly<Record<string, string>>;
7777
}
7878

7979
/**

packages/angular/ssr/test/app-engine_spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,66 @@ describe('AngularAppEngine', () => {
157157
});
158158
});
159159

160+
describe('Localized app with single locale', () => {
161+
beforeAll(() => {
162+
setAngularAppEngineManifest({
163+
entryPoints: {
164+
it: createEntryPoint('it'),
165+
},
166+
supportedLocales: { 'it': 'it' },
167+
basePath: '/',
168+
});
169+
170+
appEngine = new AngularAppEngine();
171+
});
172+
173+
describe('handle', () => {
174+
it('should return null for requests to unknown pages', async () => {
175+
const request = new Request('https://example.com/unknown/page');
176+
const response = await appEngine.handle(request);
177+
expect(response).toBeNull();
178+
});
179+
180+
it('should return a rendered page with correct locale', async () => {
181+
const request = new Request('https://example.com/it/ssr');
182+
const response = await appEngine.handle(request);
183+
expect(await response?.text()).toContain('SSR works IT');
184+
});
185+
186+
it('should correctly render the content when the URL ends with "index.html" with correct locale', async () => {
187+
const request = new Request('https://example.com/it/ssr/index.html');
188+
const response = await appEngine.handle(request);
189+
expect(await response?.text()).toContain('SSR works IT');
190+
expect(response?.headers?.get('Content-Language')).toBe('it');
191+
});
192+
193+
it('should return a serve prerendered page with correct locale', async () => {
194+
const request = new Request('https://example.com/it/ssg');
195+
const response = await appEngine.handle(request);
196+
expect(await response?.text()).toContain('SSG works IT');
197+
expect(response?.headers?.get('Content-Language')).toBe('it');
198+
});
199+
200+
it('should correctly serve the prerendered content when the URL ends with "index.html" with correct locale', async () => {
201+
const request = new Request('https://example.com/it/ssg/index.html');
202+
const response = await appEngine.handle(request);
203+
expect(await response?.text()).toContain('SSG works IT');
204+
});
205+
206+
it('should return null for requests to unknown pages in a locale', async () => {
207+
const request = new Request('https://example.com/it/unknown/page');
208+
const response = await appEngine.handle(request);
209+
expect(response).toBeNull();
210+
});
211+
212+
it('should return null for requests to file-like resources in a locale', async () => {
213+
const request = new Request('https://example.com/it/logo.png');
214+
const response = await appEngine.handle(request);
215+
expect(response).toBeNull();
216+
});
217+
});
218+
});
219+
160220
describe('Non-localized app', () => {
161221
beforeAll(() => {
162222
@Component({

0 commit comments

Comments
 (0)