Files
yourpart3/frontend/scripts/build-ceb-socialnetwork-patch.mjs
Torsten Schulz (local) f715c6125d
All checks were successful
Deploy to production / deploy (push) Successful in 2m48s
feat(i18n): implement deep merging for locale chunks and enhance Cebuano translations
- Introduced a deep merge function to combine locale chunks, improving the handling of language data for Cebuano.
- Updated Cebuano locale files with comprehensive translations, including new sections for admin, social network, and settings.
- Enhanced existing translations for clarity and consistency across various components, ensuring a better user experience.
- Added new fields in the settings and profile sections to capture more user attributes, improving personalization options.
2026-04-07 16:23:11 +02:00

283 lines
7.6 KiB
JavaScript

/**
* Baut scripts/ceb-patches/socialnetwork-patch.json für deepMerge in ceb/socialnetwork.json.
* Benötigt: /tmp/vocab-patch-en.json (wird vom Aufrufer erzeugt)
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const root = path.resolve(__dirname, '..');
function readJson(p) {
return JSON.parse(fs.readFileSync(p, 'utf8'));
}
const PHRASES = [
['Vocabulary trainer', 'Trainer sa bokabularyo'],
['vocabulary', 'bokabularyo'],
['Vocabulary', 'Bokabularyo'],
['Chapter Test', 'Tsek sa kapitulo'],
['chapter test', 'tsek sa kapitulo'],
['Create ', 'Paghimo og '],
['Create', 'Paghimo'],
['Delete ', 'Tangtanga ang '],
['Delete', 'Tangtanga'],
['Save', 'I-save'],
['Cancel', 'Kanselahon'],
['Close', 'Isira'],
['Open ', 'Ablihi ang '],
['Open', 'Ablihi'],
['Search', 'Pangita'],
['Loading', 'Nagkarga'],
['Error', 'Sayop'],
['Success', 'Malampuson'],
['lesson', 'leksiyon'],
['Lesson', 'Leksiyon'],
['lessons', 'mga leksiyon'],
['Lessons', 'Mga leksiyon'],
['course', 'kurso'],
['Course', 'Kurso'],
['courses', 'mga kurso'],
['Courses', 'Mga kurso'],
['language', 'pinulongan'],
['Language', 'Pinulongan'],
['chapter', 'kapitulo'],
['Chapter', 'Kapitulo'],
['practice', 'praktis'],
['Practice', 'Praktis'],
['correct', 'tama'],
['Correct', 'Tama'],
['wrong', 'sayop'],
['Wrong', 'Sayop'],
['Next', 'Sunod'],
['Back', 'Balik'],
['Skip', 'Laktaw'],
['Check', 'Susihi'],
['Start ', 'Sugdi ang '],
['Start', 'Sugdi'],
['Stop ', 'Hunong ang '],
['Stop', 'Hunong'],
['Continue', 'Padayon'],
['Review', 'Balik-balik'],
['Title', 'Titulo'],
['Description', 'Deskripsiyon'],
['Optional', 'Opsyonal'],
['Invalid', 'Dili balido'],
['Subscribe', 'Mag-subscribe'],
['Share', 'Ipaambit'],
['Owner', 'Tag-iya'],
['Public', 'Publiko'],
['Difficulty', 'Kalisod'],
['Enrolled', 'Na-enroll'],
['Completed', 'Nahuman'],
['Grammar', 'Gramatika'],
['Culture', 'Kultura'],
['Conversation', 'Panag-istoryahanay'],
['Recording', 'Nagrekord'],
['minutes', 'ka minuto'],
['minute', 'minuto'],
['Mother tongue', 'Pinulongan nga inahan'],
['Learning language', 'Pinulongan nga tun-an'],
['Native language', 'Pinulongan nga lumad'],
['Target language', 'Pinulongan nga target'],
['learning', 'pagkat-on'],
['Learning', 'Pagkat-on'],
['explanation', 'pasabot'],
['Explanation', 'Pasabot'],
['assistant', 'katabang'],
['Assistant', 'Katabang'],
['message', 'mensahe'],
['Message', 'Mensahe'],
['Send ', 'Padal-a ang '],
['Send', 'Padala'],
['Could not', 'Dili ma'],
['No ', 'Walay '],
['Not ', 'Dili '],
['You ', 'Ikaw '],
[' your ', ' imong '],
['Please ', 'Palihog '],
['really ', 'tinuod nga '],
['Really ', 'Tinuod nga '],
['the ', 'ang '],
['The ', 'Ang '],
['and ', 'ug '],
[' or ', ' o '],
['with ', 'uban sa '],
[' for ', ' para sa '],
[' to ', ' aron '],
[' in ', ' sa '],
[' on ', ' sa '],
[' at ', ' sa '],
[' of ', ' sa '],
[' from ', ' gikan sa '],
[' this ', ' kini nga '],
['This ', 'Kini nga '],
[' all ', ' tanan nga '],
['All ', 'Tanan nga '],
[' first', ' una'],
['First ', 'Una '],
[' after ', ' human sa '],
[' before ', ' sa wala pa '],
[' when ', ' kung '],
[' have ', ' naay '],
[' has ', ' naay '],
];
function translateUiString(s) {
if (typeof s !== 'string') return s;
let out = s;
for (const [en, ceb] of PHRASES) {
if (out.includes(en)) out = out.split(en).join(ceb);
}
return out;
}
function mapStringsDeep(node) {
if (typeof node === 'string') return translateUiString(node);
if (node === null || typeof node !== 'object' || Array.isArray(node)) return node;
const out = {};
for (const k of Object.keys(node)) {
out[k] = mapStringsDeep(node[k]);
}
return out;
}
const vocabEnPath = '/tmp/vocab-patch-en.json';
if (!fs.existsSync(vocabEnPath)) {
console.error('Missing', vocabEnPath, '— run vocab key export first');
process.exit(1);
}
const vocabMapped = mapStringsDeep(readJson(vocabEnPath));
const profilePart = {
values: {
pubichair: {
none: 'Wala',
short: 'Mubo',
medium: 'Tunga-tunga',
long: 'Taas',
hairy: 'Natural',
waxed: 'Wax',
landingstrip: 'Landing strip',
other: 'Uban',
bikinizone: 'Zona sa bikini lamang',
},
eyecolor: {
blue: 'Asul',
green: 'Berde',
brown: 'Brown',
black: 'Itom',
grey: 'Abohon',
hazel: 'Hazel',
amber: 'Amber',
red: 'Pula',
other: 'Uban',
},
haircolor: {
black: 'Itom',
brown: 'Brown',
blonde: 'Blonde',
red: 'Pula',
grey: 'Abohon',
white: 'Puti',
other: 'Uban',
},
hairlength: {
short: 'Mubo',
medium: 'Tunga-tunga',
long: 'Taas',
bald: 'Kalbo',
other: 'Uban',
},
skincolor: {
light: 'Klaro',
medium: 'Tunga-tunga',
dark: 'Itom',
other: 'Uban',
},
freckles: {
much: 'Daghan',
medium: 'Tunga-tunga',
less: 'Ubos',
none: 'Wala',
},
},
pubichair: 'Buhok sa pribado',
penislength: 'Taas sa penis',
brasize: 'Sukod sa bra',
piercings: 'Mga piercing',
tattoos: 'Mga tattoo',
eyecolor: 'Kolor sa mata',
haircolor: 'Kolor sa buhok',
hairlength: 'Taas sa buhok',
freckles: 'Mga batik',
skincolor: 'Kolor sa panit',
};
const forumPart = {
pagination: {
first: 'Unang panid',
previous: 'Miaging panid',
next: 'Sunod nga panid',
last: 'Kataposang panid',
page: 'Panid <<page>> sa <<of>>',
},
};
const eroticPart = {
requestInfoTitle: 'Gipasa nga prueba',
documentLabel: 'Dokumento sa beripikasyon',
noteLabel: 'Mubo nga nota para sa moderation',
settingsLink: 'Ablihi ang account settings',
verificationHintTitle: 'Nota sa beripikasyon',
verificationHintBody:
'Mahimo kang magpadala og hulagway. Kung dili klaro ang imong edad didto, ibalibaran ang hangyo ug kinahanglan nimo og ID.',
notifications: {
approved: 'Gi-aprub sa moderation ang imong pag-abli sa erotik nga lugar.',
rejected:
'Gibalibaran ang imong hangyo sa erotik. Kung dili klaro ang edad sa hulagway, palihog ipadala ang ID.',
},
noVideos: 'Wala pa kay na-upload nga erotik nga mga video.',
intro: 'Na-abli na ang lugar. Ang mga module sa hulagway ug video mosunod sa sunod nga lakang.',
enabledTitle: 'Na-abli na ang access',
enabledBody:
'Ang imong account na-enable na sa erotik nga lugar. Ang hiwalay nga mga view sa hulagway ug video himoon pa.',
roadmapTitle: 'Sunod',
roadmapModeration: 'hiwalay nga agianan sa moderation ug reporting',
roadmapUpload: 'dedikadong mga view sa upload ug pagdumala',
roadmapSeparation: 'klaro nga pagbulag gikan sa normal nga galeriya',
status: {
none: {
title: 'Wala pa ma-abli',
body: 'Makita ang lugar, pero naka-lock pa hangtod sa pag-aprub sa moderator.',
},
pending: {
title: 'Naghuwat sa pagsusi',
body: 'Ang imong hangyo naghuwat sa moderation.',
},
approved: {
title: 'Na-abli na',
body: 'Na-abli na ang erotik nga lugar para sa imong account.',
},
rejected: {
title: 'Gibalibaran ang hangyo',
body: 'Ang kataposang hangyo wala ma-aprub. Mahimo kang magpadala og bag-o.',
},
},
};
const patch = {
socialnetwork: {
profile: profilePart,
forum: forumPart,
erotic: eroticPart,
vocab: vocabMapped,
},
};
const outPath = path.join(root, 'scripts', 'ceb-patches', 'socialnetwork-patch.json');
fs.mkdirSync(path.dirname(outPath), { recursive: true });
fs.writeFileSync(outPath, JSON.stringify(patch, null, 2) + '\n', 'utf8');
console.log('Wrote', outPath);