Skip to content

Commit 08e07e3

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 4ac89c5 commit 08e07e3

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
@@ -160,6 +160,66 @@ describe('AngularAppEngine', () => {
160160
});
161161
});
162162

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

0 commit comments

Comments
 (0)