From 47277114da0d1c60a21d254b2450f790e7213633 Mon Sep 17 00:00:00 2001 From: Julien Gautier Date: Mon, 11 May 2026 19:46:13 +0200 Subject: [PATCH] =?UTF-8?q?feat(portal-shell):=20i18n=20string=20sweep=20?= =?UTF-8?q?=E2=80=94=20mark=20UI=20strings=20+=20FR=20translations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Continue ADR-0019 implementation. Mark every UI string surfaced by the shell with `i18n="@@id"` (templates) or `$localize` (TypeScript) and populate `messages.fr.xlf` with French translations. 43 trans- units total: skip-link, header, sidebar, theme switcher, footer, home page, route titles. What's marked: - `app.html` skip-link. - `header.html` brand wordmark, search label + placeholder, action buttons (notifications / help / settings), user-menu placeholder. - `sidebar.ts` MENU data (group + item labels) and a computed aria- label for the toggle button (Expand / Collapse). - `sidebar.html` aside / sections / role / collapse strings. - `theme-switcher.ts` MODE_OPTIONS labels + computed trigger aria ("Theme: (open menu)" with a named placeholder). - `theme-switcher.html` menu aria-label. - `footer.html` aria-labels + copyright. The two accessibility-page link labels stay bilingual on purpose (one per language, each carrying its `lang` attribute) — the dual-link pattern goes away in the upcoming route-fusion PR. - `home.html` welcome heading + intro + status widget labels. - `app.routes.ts` browser tab titles. The `/accessibility` and `/accessibilite` routes share one title key; the route-fusion PR will collapse them to a single localised route. Tooling: - Add `"@angular/localize"` to the `types` array in both `tsconfig.app.json` and `tsconfig.spec.json` so TypeScript resolves the `$localize` global. Translation choices worth flagging: - Wordmark: "APF Portal" → "Portail APF" (consistent with the route title key). - "System" theme mode → "Système". - "Anonymous" role → "Anonyme"; "Role:" → "Rôle :" (French uses a non-breaking-space before the colon — typographic convention, preserved in the XLIFF target). Verification: - Production build emits both locales (`dist/.../{en,fr}/`). Spot-checked the FR bundle: no leftover English source text on any of the swept strings, route titles, or the home page intro. - Initial bundle: 129 kB gzip per locale (vs 122 kB before). +7 kB gzip absorbs the i18n marker metadata + the FR translation data embedded in the FR bundle. Well under the 300 KB budget. - 36 / 36 specs unchanged (they run in the source locale, so the English assertions still match). Out of scope (each its own follow-up PR): - Locale switcher in the footer + `__Host-portal_locale` cookie + smart `/` redirect. - Collapse `/accessibility` + `/accessibilite` into one localised route. - CI gate that fails the build on a missing translation. --- apps/portal-shell/src/app/app.html | 2 +- apps/portal-shell/src/app/app.routes.ts | 13 +- .../src/app/components/footer/footer.html | 7 +- .../src/app/components/header/header.html | 11 +- .../src/app/components/sidebar/sidebar.html | 22 +- .../src/app/components/sidebar/sidebar.ts | 35 ++- .../theme-switcher/theme-switcher.html | 10 +- .../theme-switcher/theme-switcher.ts | 13 +- .../portal-shell/src/app/pages/home/home.html | 40 +++- apps/portal-shell/src/locale/messages.fr.xlf | 211 +++++++++++++++++- apps/portal-shell/tsconfig.app.json | 2 +- apps/portal-shell/tsconfig.spec.json | 2 +- 12 files changed, 312 insertions(+), 56 deletions(-) diff --git a/apps/portal-shell/src/app/app.html b/apps/portal-shell/src/app/app.html index 0f124a2..d5b6da7 100644 --- a/apps/portal-shell/src/app/app.html +++ b/apps/portal-shell/src/app/app.html @@ -1,4 +1,4 @@ - +
diff --git a/apps/portal-shell/src/app/app.routes.ts b/apps/portal-shell/src/app/app.routes.ts index 42fd526..03db77f 100644 --- a/apps/portal-shell/src/app/app.routes.ts +++ b/apps/portal-shell/src/app/app.routes.ts @@ -1,11 +1,18 @@ import { Route } from '@angular/router'; +// Tab titles per route — marked with `$localize` so each locale's +// bundle ships its own. The `/accessibility` and `/accessibilite` +// pair shares a title key; the upcoming route fusion (per ADR-0019) +// collapses them to a single localised route. +const homeTitle = $localize`:@@route.home.title:APF Portal`; +const accessibilityTitle = $localize`:@@route.accessibility.title:Accessibility statement · APF Portal`; + export const appRoutes: Route[] = [ { path: '', pathMatch: 'full', loadComponent: () => import('./pages/home/home').then((m) => m.Home), - title: 'APF Portal', + title: homeTitle, }, // RGAA + ADR-0016: the accessibility statement must be reachable // from both locales' canonical paths. Same component, content @@ -15,13 +22,13 @@ export const appRoutes: Route[] = [ loadComponent: () => import('./pages/accessibility/accessibility').then((m) => m.AccessibilityStatement), data: { lang: 'en' }, - title: 'Accessibility statement · APF Portal', + title: accessibilityTitle, }, { path: 'accessibilite', loadComponent: () => import('./pages/accessibility/accessibility').then((m) => m.AccessibilityStatement), data: { lang: 'fr' }, - title: 'Déclaration d’accessibilité · APF Portal', + title: accessibilityTitle, }, ]; diff --git a/apps/portal-shell/src/app/components/footer/footer.html b/apps/portal-shell/src/app/components/footer/footer.html index e845a8d..b7f8081 100644 --- a/apps/portal-shell/src/app/components/footer/footer.html +++ b/apps/portal-shell/src/app/components/footer/footer.html @@ -1,14 +1,16 @@
-

© {{ year }} APF France handicap

+

© {{ year }} APF France handicap

-