feat(i18n): implement deep merging for locale chunks and enhance Cebuano translations
All checks were successful
Deploy to production / deploy (push) Successful in 2m48s
All checks were successful
Deploy to production / deploy (push) Successful in 2m48s
- 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.
This commit is contained in:
282
frontend/scripts/build-ceb-socialnetwork-patch.mjs
Normal file
282
frontend/scripts/build-ceb-socialnetwork-patch.mjs
Normal file
@@ -0,0 +1,282 @@
|
||||
/**
|
||||
* 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);
|
||||
Reference in New Issue
Block a user