All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 54s
- Changed file permissions from 644 to 755 for various files in the mobile-app and mobile-app_legacy_rn_expo directories, ensuring executable permissions where necessary. - Added a new SQL migration script to the backend to introduce missing columns for club billing and invoice settings in the clubs table, maintaining synchronization with the current Sequelize model.
105 lines
3.1 KiB
JavaScript
Executable File
105 lines
3.1 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/**
|
|
* de-CH: Alle ererbten de-Strings als Override mit CH-Orthografie (ß→ss, …).
|
|
* Bestehende de-CH-Overrides bleiben erhalten.
|
|
*/
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const ROOT = path.resolve(__dirname, '..');
|
|
const LOCALES_DIR = path.join(ROOT, 'frontend', 'src', 'i18n', 'locales');
|
|
|
|
const CH_REPLACEMENTS = [
|
|
[/ß/g, 'ss'],
|
|
[/Straße/g, 'Strasse'],
|
|
[/straße/g, 'strasse'],
|
|
[/Grüße/g, 'Grüsse'],
|
|
[/grüße/g, 'grüsse'],
|
|
[/Gruß/g, 'Gruss'],
|
|
[/gruß/g, 'gruss'],
|
|
];
|
|
|
|
function toSwiss(text) {
|
|
let out = text;
|
|
for (const [re, rep] of CH_REPLACEMENTS) {
|
|
out = out.replace(re, rep);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function flatten(obj, prefix = '', out = {}) {
|
|
for (const [key, value] of Object.entries(obj || {})) {
|
|
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
flatten(value, nextKey, out);
|
|
} else if (typeof value === 'string') {
|
|
out[nextKey] = value;
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function deepMerge(base, override) {
|
|
if (!base || typeof base !== 'object' || Array.isArray(base)) return override ?? base;
|
|
const result = { ...base };
|
|
for (const [key, value] of Object.entries(override || {})) {
|
|
if (
|
|
value && typeof value === 'object' && !Array.isArray(value) &&
|
|
result[key] && typeof result[key] === 'object' && !Array.isArray(result[key])
|
|
) {
|
|
result[key] = deepMerge(result[key], value);
|
|
} else {
|
|
result[key] = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function setByPath(obj, dotPath, value) {
|
|
const parts = dotPath.split('.');
|
|
let cur = obj;
|
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
if (!cur[parts[i]] || typeof cur[parts[i]] !== 'object') cur[parts[i]] = {};
|
|
cur = cur[parts[i]];
|
|
}
|
|
cur[parts[parts.length - 1]] = value;
|
|
}
|
|
|
|
function buildOverrides(deFlat, targetFlat) {
|
|
const out = {};
|
|
for (const [key, value] of Object.entries(targetFlat)) {
|
|
if (value !== deFlat[key]) setByPath(out, key, value);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
const de = JSON.parse(fs.readFileSync(path.join(LOCALES_DIR, 'de.json'), 'utf8'));
|
|
const ch = JSON.parse(fs.readFileSync(path.join(LOCALES_DIR, 'de-CH.json'), 'utf8'));
|
|
const deFlat = flatten(de);
|
|
const merged = flatten(deepMerge(JSON.parse(JSON.stringify(de)), ch));
|
|
|
|
let patched = 0;
|
|
for (const key of Object.keys(deFlat)) {
|
|
if (merged[key] === deFlat[key]) {
|
|
const swiss = toSwiss(deFlat[key]);
|
|
if (swiss !== deFlat[key] || !Object.prototype.hasOwnProperty.call(flatten(ch), key)) {
|
|
merged[key] = swiss;
|
|
if (swiss !== deFlat[key]) patched++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Alle Keys: CH-Text als Override wenn abweichend von de
|
|
for (const key of Object.keys(deFlat)) {
|
|
const swiss = toSwiss(deFlat[key]);
|
|
if (merged[key] !== deFlat[key]) continue;
|
|
merged[key] = swiss;
|
|
}
|
|
|
|
const overrides = buildOverrides(deFlat, merged);
|
|
const outPath = path.join(LOCALES_DIR, 'de-CH.json');
|
|
fs.writeFileSync(outPath, `${JSON.stringify(overrides, null, 2)}\n`, 'utf8');
|
|
|
|
const stillDe = Object.keys(deFlat).filter((k) => merged[k] === deFlat[k]).length;
|
|
console.log(`de-CH: overrides=${Object.keys(flatten(overrides)).length}, ss-patched=${patched}, stillDe=${stillDe}`);
|