From ec84f31bc71fcb5dfda093f849c9b8feb680f05d Mon Sep 17 00:00:00 2001 From: Cyril Date: Thu, 31 Jul 2025 11:19:34 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F(frontend)=20set=20html=20lan?= =?UTF-8?q?g=20attribute=20dynamically=20based=20on=20current=20loc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ensures proper language tag is set for accessibility and SEO compliance Signed-off-by: Cyril --- CHANGELOG.md | 4 +- .../__tests__/app-impress/language.spec.ts | 6 +++ src/frontend/apps/impress/src/i18n/config.ts | 1 + .../apps/impress/src/i18n/initI18n.ts | 14 +++++- .../apps/impress/src/pages/_document.tsx | 44 ++++++++++++++----- 5 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 src/frontend/apps/impress/src/i18n/config.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 876698384..92b65a9d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,9 @@ and this project adheres to - ♻️(frontend) redirect to doc after duplicate #1175 - 🔧(project) change env.d system by using local files #1200 - ⚡️(frontend) improve tree stability #1207 -- ⚡️(frontend) improve accessibility #1232 +- ⚡️(frontend) improve accessibility + - #1232 + - #1248 - 🛂(frontend) block drag n drop when not desktop #1239 ### Fixed diff --git a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts index 1d616cc49..166ac6537 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts @@ -26,6 +26,8 @@ test.describe.serial('Language', () => { test('checks language switching', async ({ page }) => { const header = page.locator('header').first(); + await expect(page.locator('html')).toHaveAttribute('lang', 'en-us'); + // initial language should be english await expect( page.getByRole('button', { @@ -36,6 +38,8 @@ test.describe.serial('Language', () => { // switch to french await waitForLanguageSwitch(page, TestLanguage.French); + await expect(page.locator('html')).toHaveAttribute('lang', 'fr'); + await expect( header.getByRole('button').getByText('Français'), ).toBeVisible(); @@ -47,6 +51,8 @@ test.describe.serial('Language', () => { await expect(header.getByRole('button').getByText('Deutsch')).toBeVisible(); await expect(page.getByLabel('Abmelden')).toBeVisible(); + + await expect(page.locator('html')).toHaveAttribute('lang', 'de'); }); test('checks that backend uses the same language as the frontend', async ({ diff --git a/src/frontend/apps/impress/src/i18n/config.ts b/src/frontend/apps/impress/src/i18n/config.ts new file mode 100644 index 000000000..99250a452 --- /dev/null +++ b/src/frontend/apps/impress/src/i18n/config.ts @@ -0,0 +1 @@ +export const fallbackLng = 'en'; diff --git a/src/frontend/apps/impress/src/i18n/initI18n.ts b/src/frontend/apps/impress/src/i18n/initI18n.ts index 090226407..15d97c0bf 100644 --- a/src/frontend/apps/impress/src/i18n/initI18n.ts +++ b/src/frontend/apps/impress/src/i18n/initI18n.ts @@ -2,6 +2,7 @@ import i18next from 'i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; +import { fallbackLng } from './config'; import resources from './translations.json'; // Add an initialization guard @@ -16,7 +17,7 @@ if (!isInitialized && !i18next.isInitialized) { .use(initReactI18next) .init({ resources, - fallbackLng: 'en', + fallbackLng, debug: false, detection: { order: ['cookie', 'navigator'], @@ -35,6 +36,17 @@ if (!isInitialized && !i18next.isInitialized) { nsSeparator: false, keySeparator: false, }) + .then(() => { + if (typeof document !== 'undefined') { + document.documentElement.setAttribute( + 'lang', + i18next.language || fallbackLng, + ); + i18next.on('languageChanged', (lang) => { + document.documentElement.setAttribute('lang', lang); + }); + } + }) .catch((e) => console.error('i18n initialization failed:', e)); } diff --git a/src/frontend/apps/impress/src/pages/_document.tsx b/src/frontend/apps/impress/src/pages/_document.tsx index 9f81db4d9..27a0f30e8 100644 --- a/src/frontend/apps/impress/src/pages/_document.tsx +++ b/src/frontend/apps/impress/src/pages/_document.tsx @@ -1,13 +1,33 @@ -import { Head, Html, Main, NextScript } from 'next/document'; - -export default function RootLayout() { - return ( - - - -
- - - - ); +import Document, { + DocumentContext, + Head, + Html, + Main, + NextScript, +} from 'next/document'; + +import { fallbackLng } from '../i18n/config'; + +class MyDocument extends Document<{ locale: string }> { + static async getInitialProps(ctx: DocumentContext) { + const initialProps = await Document.getInitialProps(ctx); + return { + ...initialProps, + locale: ctx.locale || fallbackLng, + }; + } + + render() { + return ( + + + +
+ + + + ); + } } + +export default MyDocument;