Skip to content

Commit 3c374e3

Browse files
rvveberAntoLC
authored andcommitted
🐛(i18n) same frontend and backend language using shared cookies
frontend: switch to cookie-based language selection backend: use cookie for language
1 parent ff364f8 commit 3c374e3

File tree

9 files changed

+58
-96
lines changed

9 files changed

+58
-96
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to
1818
## Fixed
1919

2020
- 🐛(backend) require right to manage document accesses to see invitations #369
21+
- 🐛(i18n) same frontend and backend language using shared cookies #365
2122
- 🐛(frontend) add default toolbar buttons #355
2223

2324

@@ -27,7 +28,7 @@ and this project adheres to
2728

2829
- ✨AI to doc editor #250
2930
- ✨(backend) allow uploading more types of attachments #309
30-
- ✨(frontend) add buttons to copy document to clipboard as HTML/Markdown #300
31+
- ✨(frontend) add buttons to copy document to clipboard as HTML/Markdown #318
3132

3233
## Changed
3334

src/backend/impress/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ class Base(Configuration):
223223

224224
# Languages
225225
LANGUAGE_CODE = values.Value("en-us")
226+
LANGUAGE_COOKIE_NAME = "docs_language" # cookie & language is set from frontend
226227

227228
DRF_NESTED_MULTIPART_PARSER = {
228229
# output of parser is converted to querydict

src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,38 @@ test.describe('Language', () => {
2525
}),
2626
).toBeVisible();
2727
});
28+
29+
test('checks that backend uses the same language as the frontend', async ({
30+
page,
31+
}) => {
32+
// Helper function to intercept and assert 404 response
33+
const check404Response = async (expectedDetail: string) => {
34+
const expectedBackendResponse = page.waitForResponse(
35+
(response) =>
36+
response.url().includes('/api') &&
37+
response.url().includes('non-existent-doc-uuid') &&
38+
response.status() === 404,
39+
);
40+
41+
// Trigger the specific 404 XHR response by navigating to a non-existent document
42+
await page.goto('/docs/non-existent-doc-uuid');
43+
44+
// Assert that the intercepted error message is in the expected language
45+
const interceptedBackendResponse = await expectedBackendResponse;
46+
expect(await interceptedBackendResponse.json()).toStrictEqual({
47+
detail: expectedDetail,
48+
});
49+
};
50+
51+
// Check for English 404 response
52+
await check404Response('Not found.');
53+
54+
// Switch language to French
55+
const header = page.locator('header').first();
56+
await header.getByRole('combobox').getByText('English').click();
57+
await header.getByRole('option', { name: 'Français' }).click();
58+
59+
// Check for French 404 response
60+
await check404Response('Pas trouvé.');
61+
});
2862
});

src/frontend/apps/impress/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@openfun/cunningham-react": "2.9.4",
2424
"@tanstack/react-query": "5.59.15",
2525
"i18next": "23.16.2",
26+
"i18next-browser-languagedetector": "8.0.0",
2627
"idb": "8.0.0",
2728
"lodash": "4.17.21",
2829
"luxon": "3.5.0",

src/frontend/apps/impress/src/i18n/__tests__/utils.spec.ts

Lines changed: 0 additions & 55 deletions
This file was deleted.

src/frontend/apps/impress/src/i18n/conf.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ export const LANGUAGES_ALLOWED: { [key: string]: string } = {
22
en: 'English',
33
fr: 'Français',
44
};
5-
export const LANGUAGE_LOCAL_STORAGE = 'impress-language';
6-
export const BASE_LANGUAGE = 'fr';
5+
export const LANGUAGE_COOKIE_NAME = 'docs_language';
6+
export const BASE_LANGUAGE = 'en';
Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
import i18n from 'i18next';
2+
import LanguageDetector from 'i18next-browser-languagedetector';
23
import { initReactI18next } from 'react-i18next';
34

4-
import { LANGUAGES_ALLOWED, LANGUAGE_LOCAL_STORAGE } from './conf';
5+
import { BASE_LANGUAGE, LANGUAGES_ALLOWED, LANGUAGE_COOKIE_NAME } from './conf';
56
import resources from './translations.json';
6-
import { getLanguage } from './utils';
77

88
i18n
9+
.use(LanguageDetector)
910
.use(initReactI18next)
1011
.init({
1112
resources,
12-
lng: getLanguage(),
13+
fallbackLng: BASE_LANGUAGE,
14+
supportedLngs: Object.keys(LANGUAGES_ALLOWED),
15+
detection: {
16+
order: ['cookie', 'navigator'], // detection order
17+
caches: ['cookie'], // Use cookies to store the language preference
18+
lookupCookie: LANGUAGE_COOKIE_NAME,
19+
cookieMinutes: 525600, // Expires after one year
20+
},
1321
interpolation: {
1422
escapeValue: false,
1523
},
@@ -20,11 +28,4 @@ i18n
2028
throw new Error('i18n initialization failed');
2129
});
2230

23-
// Save language in local storage
24-
i18n.on('languageChanged', (lng) => {
25-
if (typeof window !== 'undefined') {
26-
localStorage.setItem(LANGUAGE_LOCAL_STORAGE, lng);
27-
}
28-
});
29-
3031
export default i18n;

src/frontend/apps/impress/src/i18n/utils.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/frontend/yarn.lock

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7167,6 +7167,13 @@ human-signals@^2.1.0:
71677167
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
71687168
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
71697169

7170+
7171+
version "8.0.0"
7172+
resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz#b6fdd9b43af67c47f2c26c9ba27710a1eaf31e2f"
7173+
integrity sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==
7174+
dependencies:
7175+
"@babel/runtime" "^7.23.2"
7176+
71707177
71717178
version "9.0.2"
71727179
resolved "https://registry.yarnpkg.com/i18next-parser/-/i18next-parser-9.0.2.tgz#f9d627422d33c352967556c8724975d58f1f5a95"

0 commit comments

Comments
 (0)