feat(i18n): add French language support and enhance localization
All checks were successful
Deploy to production / deploy (push) Successful in 2m48s

- Introduced French as a supported language across the application, updating locale files and adding translations for various components.
- Enhanced language handling logic to accommodate French, ensuring proper detection and fallback mechanisms.
- Updated UI elements to include French language options, improving accessibility for French-speaking users.
- Refactored SEO handling to include French in hreflang links, enhancing search engine indexing for multilingual content.
- Added new scripts for managing French translations and ensuring consistency across language files.
This commit is contained in:
Torsten Schulz (local)
2026-04-07 18:04:03 +02:00
parent f715c6125d
commit f7030bbabe
56 changed files with 5220 additions and 175 deletions

View File

@@ -5,6 +5,7 @@ import router from '../router';
import apiClient from '../utils/axios.js';
import { io } from 'socket.io-client';
import { getDaemonSocketUrl, getSocketIoUrl } from '../utils/appConfig.js';
import { SUPPORTED_UI_LOCALES } from '../i18n/supportedLocales.js';
const AUTH_KEYS = ['isLoggedIn', 'user', 'userid'];
@@ -30,8 +31,6 @@ function clearAuthStorage() {
});
}
const SUPPORTED_UI_LOCALES = ['de', 'en', 'ceb', 'es'];
function persistAuthStorage(user, rememberMe) {
const targetStorage = rememberMe ? localStorage : sessionStorage;
clearAuthStorage();
@@ -78,7 +77,15 @@ const store = createStore({
if (browserLanguage.startsWith('de')) {
return 'de';
}
if (browserLanguage.startsWith('fr')) {
return 'fr';
}
if (browserLanguage.startsWith('es')) {
return 'es';
}
const allLanguages = navigator.languages || [navigator.language];
for (const lang of allLanguages) {
if (lang.startsWith('ceb') || lang.startsWith('bis')) {
@@ -97,7 +104,19 @@ const store = createStore({
}
}
}
for (const lang of allLanguages) {
if (lang.startsWith('fr')) {
return 'fr';
}
}
for (const lang of allLanguages) {
if (lang.startsWith('es')) {
return 'es';
}
}
return 'en';
})(),
menu: JSON.parse(localStorage.getItem('menu')) || [],
@@ -147,9 +166,13 @@ const store = createStore({
}
const germanSpeakingCountries = ['de', 'at', 'ch', 'li'];
if (browserLanguage.startsWith('de')) {
state.language = 'de';
} else if (browserLanguage.startsWith('fr')) {
state.language = 'fr';
} else if (browserLanguage.startsWith('es')) {
state.language = 'es';
} else {
const allLanguages = navigator.languages || [navigator.language];
let isGerman = false;
@@ -173,7 +196,23 @@ const store = createStore({
}
}
}
state.language = isGerman ? 'de' : 'en';
if (isGerman) {
state.language = 'de';
return;
}
for (const lang of allLanguages) {
if (lang.startsWith('fr')) {
state.language = 'fr';
return;
}
}
for (const lang of allLanguages) {
if (lang.startsWith('es')) {
state.language = 'es';
return;
}
}
state.language = 'en';
}
},
setLanguage(state, language) {