feat(localization): expand language support and enhance UI for user settings
All checks were successful
Deploy to production / deploy (push) Successful in 3m0s

- Added support for additional UI locales including Cebuano and Spanish, improving accessibility for a broader user base.
- Updated language selection components in the AppHeader and SettingsWidget to reflect new language options, enhancing user experience.
- Enhanced localization of various UI elements across components, ensuring consistent language representation and improved user engagement.
- Implemented logic to synchronize user language preferences with backend settings, providing a seamless experience when changing languages.
This commit is contained in:
Torsten Schulz (local)
2026-04-02 07:54:44 +02:00
parent ac5d436a36
commit 6d9d69dc10
72 changed files with 1792 additions and 343 deletions

View File

@@ -4,6 +4,7 @@ import { v4 as uuidv4 } from 'uuid';
import User from '../models/community/user.js';
import UserParam from '../models/community/user_param.js';
import UserParamType from '../models/type/user_param.js';
import UserParamValue from '../models/type/user_param_value.js';
import { sendAccountActivationEmail, sendPasswordResetEmail } from './emailService.js';
import { sequelize } from '../utils/sequelize.js';
import { Op } from 'sequelize';
@@ -143,6 +144,16 @@ export const loginUser = async ({ username, password }) => {
const mappedParams = params.map(param => {
return { 'name': param.paramType.description, 'value': param.value };
});
const uiLocaleCodes = ['de', 'en', 'ceb', 'es'];
const langEntry = mappedParams.find((p) => p.name === 'language');
if (langEntry?.value && !uiLocaleCodes.includes(langEntry.value)) {
const idNum = parseInt(langEntry.value, 10);
const lookupId = Number.isNaN(idNum) ? langEntry.value : idNum;
const upv = await UserParamValue.findOne({ where: { id: lookupId } });
if (upv?.value && uiLocaleCodes.includes(upv.value)) {
langEntry.value = upv.value;
}
}
console.log('return user');
return {
id: user.hashedId,

View File

@@ -67,7 +67,7 @@ const initializeTypes = async () => {
}
const valuesList = {
gender: ['male', 'female', 'transfemale', 'transmale', 'nonbinary'],
language: ['de', 'en'],
language: ['de', 'en', 'ceb', 'es'],
eyecolor: ['blue', 'green', 'brown', 'black', 'grey', 'hazel', 'amber', 'red', 'other'],
haircolor: ['black', 'brown', 'blonde', 'red', 'grey', 'white', 'other'],
hairlength: ['short', 'medium', 'long', 'bald', 'other'],

View File

@@ -1,5 +1,9 @@
import WidgetType from '../models/type/widget_type.js';
/**
* Default rows for type.widget_type. Labels/descriptions are German for DB/admin readability;
* the web app maps known `endpoint` values to localized strings (see LoggedInView / home.dashboard.widgetLabels).
*/
const DEFAULT_WIDGET_TYPES = [
{ label: 'Termine', endpoint: '/api/termine', description: 'Bevorstehende Termine', orderId: 1 },
{ label: 'Falukant', endpoint: '/api/falukant/dashboard-widget', description: 'Charakter, Geld, Nachrichten, Kinder', orderId: 2 },