⚡️(frontend) set html lang attribute dynamically based on current loc
ensures proper language tag is set for accessibility and SEO compliance Signed-off-by: Cyril <c.gromoff@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 ({
|
||||
|
||||
1
src/frontend/apps/impress/src/i18n/config.ts
Normal file
1
src/frontend/apps/impress/src/i18n/config.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const fallbackLng = 'en';
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,33 @@
|
||||
import { Head, Html, Main, NextScript } from 'next/document';
|
||||
import Document, {
|
||||
DocumentContext,
|
||||
Head,
|
||||
Html,
|
||||
Main,
|
||||
NextScript,
|
||||
} from 'next/document';
|
||||
|
||||
export default function RootLayout() {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<body suppressHydrationWarning={process.env.NODE_ENV === 'development'}>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
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 (
|
||||
<Html lang={this.props.locale}>
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument;
|
||||
|
||||
Reference in New Issue
Block a user