CentralBackend/utils/languageUtils.js
seaznCode 427c12be3c feat: add language normalization and user settings updates
- Introduced language normalization utility functions to standardize language codes across the application.
- Updated ContractUploadController to resolve requested language from contract data and user settings.
- Enhanced authMiddleware to set preferred language in user object based on user settings.
- Added preferred_language column to user_settings table in the database.
- Implemented UserSettingsRepository to manage user settings, including preferred language updates.
- Updated DocumentTemplateService and AboContractService to support language-specific templates.
- Enhanced InvoiceService to select invoice templates based on normalized language codes.
- Added new script to compare versions of ABO contract documents.
- Refactored various services and repositories to utilize the new language normalization logic.
2026-06-07 21:13:41 +02:00

89 lines
2.7 KiB
JavaScript

const BUILTIN_LANGUAGES = [
{ languageCode: 'de', label: 'Deutsch', isEnabled: true, isCustom: false },
{ languageCode: 'en', label: 'English', isEnabled: true, isCustom: false },
{ languageCode: 'sl', label: 'Slovenian', isEnabled: true, isCustom: false },
];
function normalizeLanguageCode(value) {
const raw = String(value == null ? '' : value).trim();
if (!raw) return '';
const normalized = raw.replace('_', '-');
if (!/^[a-z]{2,5}(?:-[a-zA-Z0-9]{2,8})?$/.test(normalized)) {
return '';
}
return normalized.toLowerCase();
}
function normalizeBoolean(value, fallback) {
if (value === undefined || value === null) return fallback;
if (typeof value === 'boolean') return value;
const normalized = String(value).trim().toLowerCase();
if (['1', 'true', 'yes', 'on'].includes(normalized)) return true;
if (['0', 'false', 'no', 'off'].includes(normalized)) return false;
return fallback;
}
function compareLanguageCodes(left, right) {
const order = ['de', 'en', 'sl'];
const leftIndex = order.indexOf(left);
const rightIndex = order.indexOf(right);
if (leftIndex !== -1 || rightIndex !== -1) {
if (leftIndex === -1) return 1;
if (rightIndex === -1) return -1;
return leftIndex - rightIndex;
}
return left.localeCompare(right);
}
function mergeLanguageDescriptors(rows = []) {
const merged = new Map();
BUILTIN_LANGUAGES.forEach((entry) => {
merged.set(entry.languageCode, { ...entry });
});
rows.forEach((row) => {
const languageCode = normalizeLanguageCode(
row?.languageCode ?? row?.language_code ?? row?.code ?? row?.lang,
);
if (!languageCode) return;
const existing = merged.get(languageCode) || {
languageCode,
label: languageCode.toUpperCase(),
isEnabled: true,
isCustom: true,
};
const label = String(row?.label ?? row?.name ?? existing.label ?? languageCode.toUpperCase()).trim() || existing.label;
merged.set(languageCode, {
...existing,
languageCode,
label,
isEnabled: normalizeBoolean(row?.isEnabled ?? row?.is_enabled, existing.isEnabled),
isCustom: normalizeBoolean(row?.isCustom ?? row?.is_custom, existing.isCustom),
});
});
return Array.from(merged.values()).sort((left, right) => compareLanguageCodes(left.languageCode, right.languageCode));
}
function resolveDocumentTemplateStorageFolder(languageCode) {
const normalized = normalizeLanguageCode(languageCode);
if (normalized === 'en') return 'english';
if (normalized === 'de') return 'german';
return normalized || 'other';
}
module.exports = {
BUILTIN_LANGUAGES,
mergeLanguageDescriptors,
normalizeLanguageCode,
resolveDocumentTemplateStorageFolder,
};