feat(i18n): implement deep merging for locale chunks and enhance Cebuano translations
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:
Torsten Schulz (local)
2026-04-07 16:23:11 +02:00
parent e9f0f6c133
commit f715c6125d
17 changed files with 4380 additions and 1173 deletions

View File

@@ -0,0 +1,173 @@
/**
* Baut scripts/ceb-patches/falukant-patch.json aus /tmp/ceb-fal-miss.json (EN) mit Phrase-Mapping → Bisaya.
*/
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, '..');
const PHRASES = [
['Office', 'Opisina'],
['office', 'opisina'],
['Region', 'Rehiyon'],
['region', 'rehiyon'],
['Tax', 'Buhis'],
['tax', 'buhis'],
['Loading', 'Nagkarga'],
['Retry', 'Suwayi pag-usab'],
['Error', 'Sayop'],
['Success', 'Malampuson'],
['House', 'Balay'],
['house', 'balay'],
['Storage', 'Tipigan'],
['storage', 'tipigan'],
['Marriage', 'Kasal'],
['marriage', 'kasal'],
['Affair', 'Uyab'],
['affair', 'uyab'],
['Child', 'Bata'],
['child', 'bata'],
['Children', 'Mga bata'],
['children', 'Mga bata'],
['Name', 'Ngalan'],
['Age', 'Edad'],
['Gender', 'Sekso'],
['Action', 'Aksyon'],
['Actions', 'Mga aksyon'],
['Apply', 'Aplikar'],
['Approve', 'Aprub'],
['Reject', 'Balibari'],
['Pending', 'Naghuwat'],
['Date', 'Petsa'],
['Cost', 'Kantidad'],
['Income', 'Kita'],
['Vote', 'Boto'],
['Candidates', 'Mga kandidato'],
['Election', 'Eleksiyon'],
['Chancellor', 'Chancellor'],
['Minister', 'Ministro'],
['Governor', 'Gobernador'],
['Mayor', 'Alkalde'],
['Judge', 'Hukom'],
['Treasurer', 'Tesorero'],
['Sheriff', 'Sheriff'],
['Bank', 'Bangko'],
['Credit', 'Kredito'],
['Amount', 'Kantidad'],
['Total', 'Tanan'],
['Debtors', 'Sa utang'],
['prison', 'bilanggoan'],
['Reputation', 'Dungog'],
['Soup Kitchen', 'Comedor social'],
['Library Donation', 'Donasyon sa library'],
['Scholarships', 'Mga scholarship'],
['Build', 'Tukora'],
['Donation', 'Donasyon'],
['Party', 'Party'],
['Music', 'Musika'],
['Food', 'Pagkaon'],
['Bread', 'Pan'],
['Espionage', 'Espiya'],
['Sabotage', 'Sabotage'],
['Robbery', 'Kawat'],
['Blackmail', 'Blackmail'],
['Loot', 'Bilin'],
['Pending', 'Pending'],
['Resolved', 'Nasulbad'],
['Failed', 'Napakyas'],
['Transport', 'Transporte'],
['Route', 'Ruta'],
['Duration', 'Gidugayon'],
['Arrival', 'Pag-abot'],
['Vehicle', 'Sakyanan'],
['Branch', 'Sangang opisina'],
['branch', 'sangang opisina'],
['Average', 'Average'],
['knowledge', 'kahibalo'],
['Knowledge', 'Kahibalo'],
['Completed', 'Nahuman'],
['production', 'produksyon'],
['Production', 'Produksyon'],
['Nobility', 'Kadungganan'],
['nobility', 'kadungganan'],
['Political', 'Politikal'],
['political', 'politikal'],
['Church', 'Simbahan'],
['church', 'simbahan'],
['Health', 'Panglawas'],
['health', 'panglawas'],
['measure', 'tambal'],
['Measure', 'Tambal'],
['Pill', 'Tablet'],
['Doctor', 'Doktor'],
['Witch', 'Bruha'],
['Barber', 'Barbero'],
['Servant', 'Sulugoon'],
['servant', 'sulugoon'],
['Household', ' panimalay'],
['Tension', 'Kakulba'],
['Marriage', 'Kasal'],
['Gift', 'Regalo'],
['gift', 'regalo'],
['You ', 'Ikaw '],
['The ', 'Ang '],
[' the ', ' ang '],
[' your ', ' imong '],
[' cannot ', ' dili makahimo '],
[' can ', ' mahimo '],
[' not ', ' dili '],
[' has ', ' naay '],
[' have ', ' naay '],
[' been ', ' '],
[' was ', ' '],
[' were ', ' '],
[' are ', ' '],
[' is ', ' '],
[' and ', ' ug '],
[' or ', ' o '],
[' with ', ' uban sa '],
[' for ', ' para sa '],
[' from ', ' gikan sa '],
[' to ', ' ngadto sa '],
[' in ', ' sa '],
[' on ', ' sa '],
[' at ', ' sa '],
[' of ', ' sa '],
[' a ', ' usa ka '],
[' an ', ' usa ka '],
];
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 missPath = '/tmp/ceb-fal-miss.json';
if (!fs.existsSync(missPath)) {
console.error('Missing', missPath);
process.exit(1);
}
const inner = mapStringsDeep(JSON.parse(fs.readFileSync(missPath, 'utf8')));
const patch = { falukant: inner };
const outPath = path.join(root, 'scripts', 'ceb-patches', 'falukant-patch.json');
fs.mkdirSync(path.dirname(outPath), { recursive: true });
fs.writeFileSync(outPath, JSON.stringify(patch, null, 2) + '\n', 'utf8');
console.log('Wrote', outPath);

View 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);

View File

@@ -0,0 +1,573 @@
{
"falukant": {
"overview": {
"certificate": {
"factor": {
"avgKnowledge": "Average kahibalo",
"completedProductions": "Nahuman produksyons",
"reputation": "Dungog",
"housePosition": "Balay level",
"highestPoliticalOfficeRank": "Highest politikal opisina",
"highestChurchOfficeRank": "Highest simbahan opisina",
"nobilityLevel": "Kadungganan level",
"officePoints": "Opisina status",
"nobilityPoints": "Kadungganan status",
"reputationPoints": "Dungog status",
"housePoints": "Balay status"
},
"statusMode": {
"one_of": "At least one status condition",
"two_of": "At least two status conditions"
}
}
},
"moneyHistory": {
"activities": {
"Buy storage (type: field)": "Bought tipigan (type: field)",
"Buy storage (type: iron)": "Bought tipigan (type: iron)",
"Buy storage (type: stone)": "Bought tipigan (type: stone)",
"Buy storage (type: wood)": "Bought tipigan (type: wood)",
"health": {
"pill": "Panglawas tambal: pill",
"doctor": "Panglawas tambal: doctor",
"witch": "Panglawas tambal: witch",
"drunkOfLife": "Panglawas tambal: elixir sa life",
"barber": "Panglawas tambal: barber"
}
}
},
"house": {
"servants": {
"payLevels": {
"low": "Low",
"normal": "Normal",
"high": "Generous"
},
"staffingState": {
"label": "Staffing",
"understaffed": "Understaffed",
"fitting": "Fitting",
"overstaffed": "Overstaffed"
},
"orderState": {
"label": "Order state",
"chaotic": "Chaotic",
"strained": "Strained",
"stable": "Stable",
"excellent": "Excellent"
},
"actions": {
"hire": "Hire 1 sulugoon",
"dismiss": "Dismiss 1 sulugoon",
"tidy": "Tidy balayhold",
"hireSuccess": "Ang balayhold staff naay expanded.",
"hireError": "Ang staff could dili be expanded.",
"dismissSuccess": "A sulugoon naay dismissed.",
"dismissError": "Ang sulugoon could dili be dismissed.",
"payLevelSuccess": "Sulugoon pay naay updated.",
"payLevelError": "Sulugoon pay could dili be updated.",
"tidySuccess": "Ang balayhold naay put sa order.",
"tidyError": "Ang balayhold could dili be put sa order."
}
}
},
"branch": {
"director": {
"emptyTransport": {
"title": "Transporte without products",
"description": "Move vehicles gikan sa this sangang opisina ngadto sa another ngadto sa use them better.",
"vehicleType": "Sakyanan type",
"selectVehicle": "Select vehicle type",
"targetBranch": "Target sangang opisina",
"selectTarget": "Select target sangang opisina",
"cost": "Kantidad: {cost}",
"duration": "Gidugayon: {duration}",
"arrival": "Pag-abot: {datetime}",
"route": "Ruta",
"create": "Start transport",
"success": "Transporte started successfully.",
"error": "Sayop starting ang transport."
}
},
"taxes": {
"title": "Buhises",
"loading": "Nagkarga buhis data...",
"loadingError": "Napakyas ngadto sa load buhis data: {error}",
"retry": "Suwayi pag-usab",
"noData": "No buhis data available",
"total": "Tanan buhis",
"table": {
"region": "Rehiyon",
"taxPercent": "Buhis %"
}
}
},
"nobility": {
"requirement": {
"money": "Wealth sa least {amount}",
"cost": "Kantidad: {amount}",
"branches": "At least {amount} sangang opisinaes",
"reputation": "Popularity sa least {amount}",
"house_position": "Balay status sa least level {amount}",
"house_condition": "Balay condition sa least {amount}",
"office_rank_any": "Highest politikal o simbahan opisina sa least rank {amount}",
"office_rank_political": "Highest politikal opisina sa least rank {amount}",
"lover_count_min": "At least {amount} lovers o favorites",
"lover_count_max": "At most {amount} lovers o favorites"
}
},
"mood": {
"hopeful": "Hopeful",
"frustrated": "Frustrated",
"lonely": "Lonely",
"grateful": "Grateful",
"jealous": "Jealous",
"guilty": "Guilty",
"apathetic": "Apathetic",
"relieved": "Relieved",
"proud": "Proud",
"ashamed": "Ashamed"
},
"character": {
"patient": "Patient",
"impatient": "Impatient",
"selfish": "Selfish",
"charismatic": "Charismatic",
"empathetic": "Empathetic",
"timid": "Timid",
"stubborn": "Stubborn",
"resourceful": "Resourceful",
"reckless": "Reckless",
"disciplined": "Disciplined",
"optimistic": "Optimistic",
"pessimistic": "Pessimistic",
"manipulative": "Manipulative",
"independent": "Independent",
"dependent": "Dependent",
"adventurous": "Adventurous",
"humble": "Humble",
"vengeful": "Vengeful",
"pragmatic": "Pragmatic",
"idealistic": "Idealistic"
},
"healthview": {
"measures": {
"pill": "Tablet",
"doctor": "Doktor Visit",
"witch": "Bruha",
"drunkOfLife": "Elixir sa Life",
"barber": "Barbero"
},
"errors": {
"tooClose": "Ikaw dili makahimo perform tambals so often.",
"generic": "An error occurred."
}
},
"politics": {
"current": {
"office": "Opisina",
"region": "Rehiyon",
"income": "Kita"
},
"open": {
"office": "Opisina",
"region": "Rehiyon",
"date": "Petsa",
"candidacy": "Candidacy",
"candidacyWithAge": "Candidacy (from age 16)",
"none": "No open positions.",
"apply": "Aplikar para sa selected positions",
"minAgeHint": "Candidacy only possible gikan sa age 16.",
"ageRequirement": "All politikal opisinas require candidates ngadto sa be sa least 16 years old."
},
"too_young": "Your character too young. Applications only possible gikan sa age 16.",
"upcoming": {
"office": "Opisina",
"region": "Rehiyon",
"postDate": "Petsa",
"none": "No upcoming positions."
},
"elections": {
"office": "Opisina",
"region": "Rehiyon",
"date": "Petsa",
"posts": "Posts ngadto sa Fill",
"none": "No elections available.",
"choose": "Mga kandidato",
"vote": "Boto",
"voteAll": "Boto All",
"candidates": "Mga kandidato",
"action": "Aksyon"
},
"offices": {
"chancellor": "Chancellor",
"minister": "Ministro",
"ministry-helper": "Ministry Helper",
"governor": "Gobernador",
"super-state-administrator": "Super State Administrator",
"state-administrator": "State Administrator",
"consultant": "Consultant",
"ruler-consultant": "Ruler's Consultant",
"territorial-council-speaker": "Territorial Council Speaker",
"territorial-council": "Territorial Council",
"hangman": "Hangman",
"treasurer": "Tesorero",
"sheriff": "Sheriff",
"taxman": "Buhis Collector",
"bailif": "Bailiff",
"judge": "Hukom",
"village-major": "Village Major",
"master-builder": "Master Tukoraer",
"mayor": "Alkalde",
"town-clerk": "Town Clerk",
"beadle": "Beadle",
"council": "Council Member",
"councillor": "Councillor",
"assessor": "Assessor"
}
},
"family": {
"tabsAria": "Family sections",
"debtorsPrison": {
"familyWarning": "Ongoing debt delinquency puts strain sa kasal, balayhold ug uyabs.",
"familyImpact": "Sa utang' bilanggoan damages kasal, balayhold peace ug ang stability sa uyabs."
},
"pregnancy": {
"banner": "Ikaw expecting usa ka bata.",
"dueHint": "Expected due date"
},
"children": {
"title": "Bataren",
"name": "Ngalan",
"age": "Edad",
"gender": "Sekso",
"heir": "Heir",
"isHeir": "Heir",
"notHeir": "Not Heir",
"setAsHeir": "Set as Heir",
"heirSetSuccess": "Ang bata naay successfully set as heir.",
"heirSetError": "Sayop setting heir.",
"actions": "Aksyons",
"none": "No bataren available.",
"detailButton": "Show Details",
"addChild": "Add Bata",
"baptism": "Baptize",
"notBaptized": "Not yet baptized",
"baptismNotice": "This bata naay dili baptized yet ug therefore naay no name.",
"legitimacy": {
"legitimate": "Legitimate",
"acknowledged_bastard": "Ackahibalod illegitimate",
"hidden_bastard": "Illegitimate"
},
"otherParent": "Other parent",
"otherParentUnknown": "Unknown",
"birthContextLabel": "Origin",
"birthContextShort": {
"marriage": "Kasal",
"lover": "Uyab"
},
"birthContextLong": {
"marriage": "From kasal",
"lover": "From usa ka uyab"
},
"details": {
"title": "Bata Details"
}
},
"taxes": {
"title": "Buhises",
"loading": "Nagkarga buhis data...",
"total": "Tanan buhis",
"table": {
"region": "Rehiyon",
"taxPercent": "Buhis %"
}
},
"spouse": {
"traitsToggle": "Character traits",
"marriageSatisfaction": "Kasal Satisfaction",
"marriageState": "Kasal State",
"wooing": {
"cancel": "Cancel wooing",
"cancelConfirm": "Do you really want ngadto sa cancel wooing? Progress will be lost.",
"cancelSuccess": "Wooing naay cancelled.",
"cancelError": "Wooing could dili be cancelled.",
"cancelTooSoon": "Ikaw mahimo only cancel wooing after 24 hours."
}
},
"marriageState": {
"stable": "Stable",
"strained": "Strained",
"crisis": "Crisis"
},
"householdTension": {
"label": "Balayhold Kakulba",
"score": "Kakulba score",
"reasonsLabel": "Current causes",
"low": "Calm",
"medium": "Uneasy",
"high": "Strained",
"reasons": {
"visibleLover": "Visible uyab",
"noticeableLover": "Noticeable uyab",
"underfundedLover": "Underfunded uyab",
"acknowledgedAffair": "Ackahibalod uyab",
"statusMismatch": "Status mismatch",
"loverChild": "Bata gikan sa usa ka uyab",
"disorder": "Disorder sa ang balay",
"tooFewServants": "Too few sulugoons",
"marriageCrisis": "Kasal crisis"
}
},
"marriageActions": {
"title": "Support ang kasal",
"spendTime": "Spend time together",
"giftSmall": "Small regalo",
"giftDecent": "Decent regalo",
"giftLavish": "Lavish regalo",
"reconcile": "Reconcile dispute",
"spendTimeSuccess": "Ang time together naay stabilized ang kasal.",
"giftSuccess": "Ang regalo naay improved ang kasal.",
"reconcileSuccess": "Ang dispute naay eased para sa now.",
"actionError": "Ang action could dili be completed."
},
"notifications": {
"scandal": "A family scandal shaking imong balay.",
"loverBirth": "A bata naay born gikan sa usa ka uyab."
},
"sendgift": {
"error": {
"nogiftselected": "Please select usa ka regalo.",
"generic": "An unknown error occurred.",
"tooOften": "Ikaw can't send regalos that often.",
"insufficientFunds": "Ikaw do dili naay enough money."
},
"success": "Ang regalo naay given.",
"nextGiftAt": "Next regalo from"
}
},
"church": {
"summary": {
"highestCurrentOffice": "Highest current opisina",
"availableApplications": "Possible applications",
"supervisedApplications": "Applications ngadto sa decide",
"guidance": "Simbahan opisinas usually progress step by step. Applications normally decided by ang next higher opisina; if no player holds it, usa ka NPC may later decide.",
"none": "No simbahan opisina yet"
},
"current": {
"office": "Opisina",
"region": "Rehiyon",
"holder": "Holder",
"supervisor": "Supervisor",
"none": "No current positions available."
},
"available": {
"office": "Opisina",
"region": "Rehiyon",
"supervisor": "Supervisor",
"decision": "Decision by",
"decisionType": {
"entry": "Direct entry",
"player": "Player",
"npc": "NPC",
"interim": "Interim"
},
"seats": "Available Seats",
"action": "Aksyon",
"apply": "Aplikar",
"applySuccess": "Application submitted successfully.",
"applyError": "Sayop submitting application.",
"errors": {
"characterNotFound": "Your character could dili be found.",
"officeTypeNotFound": "Ang simbahan opisina could dili be found.",
"churchCareerTooLow": "Your previous simbahan career dili yet sufficient para sa this opisina.",
"noAvailableSeats": "There currently no free seats para sa this simbahan opisina.",
"applicationAlreadyExists": "There already usa ka open application para sa this simbahan opisina sa this rehiyon."
},
"none": "No available positions."
},
"applications": {
"office": "Opisina",
"region": "Rehiyon",
"applicant": "Applicant",
"date": "Petsa",
"action": "Aksyon",
"approve": "Aprub",
"reject": "Balibari",
"approveSuccess": "Application approved.",
"rejectSuccess": "Application rejected.",
"decideError": "Sayop making decision.",
"none": "No applications available."
},
"offices": {
"lay-preacher": "Lay Preacher",
"village-priest": "Village Priest",
"parish-priest": "Parish Priest",
"dean": "Dean",
"archdeacon": "Archdeacon",
"bishop": "Bishop",
"archbishop": "Archbishop",
"cardinal": "Cardinal",
"pope": "Pope"
},
"baptism": {
"title": "Baptism",
"table": {
"name": "First Ngalan",
"gender": "Sekso",
"age": "Edad",
"baptise": "Baptize (50)",
"newName": "Suggest Ngalan"
},
"gender": {
"male": "Boy",
"female": "Girl"
},
"success": "Ang bata naay baptized.",
"error": "Ang bata could dili be baptized."
}
},
"bank": {
"debtorsPrison": {
"titleWarning": "Kredito delinquency",
"titlePrison": "Sa utang' bilanggoan",
"descriptionWarning": "Your credits overdue. If you continue ngadto sa default, forced tambals will follow.",
"descriptionPrison": "Ikaw sa debtors' bilanggoan. New credits blocked ug imong assets will be liquidated step by step.",
"daysOverdue": "Days overdue",
"creditworthiness": "Kreditoworthiness",
"nextForcedAction": "Next forced action",
"creditBlocked": "Ikaw dili makahimo take new credits while imbilanggoaned para sa debt.",
"creditError": "Ang credit could dili be taken.",
"actions": {
"reminder": "First reminder",
"final_warning": "Final warning",
"debtors_prison": "Commitment ngadto sa debtors' bilanggoan",
"asset_seizure": "Asset seizure"
}
},
"credits": {
"table": {
"name": "Ngalan",
"amount": "Kantidad",
"reason": "Reason",
"date": "Petsa"
},
"payoff": {
"title": "Take usa ka new credit",
"height": "Kredito amount",
"remaining": "Remaining possible credit amount",
"fee": "Kredito interest",
"feeHeight": "Installment (10 payments)",
"total": "Tanan",
"confirm": "Take credit"
}
}
},
"reputation": {
"actions": {
"running": "Running...",
"dailyLimit": "Daily limit: {remaining} sa {cap} actions remaining",
"cooldown": "Cooldown: {minutes} minutes remaining",
"type": {
"soup_kitchen": "Comedor social",
"library_donation": "Donasyon sa library",
"scholarships": "Mga scholarship",
"church_hospice": "Simbahan Hospice",
"school_funding": "School Funding",
"orphanage_build": "Tukora Orphanage",
"bridge_build": "Tukora Bridge",
"hospital_donation": "Hospital Donasyon",
"patronage": "Patronage",
"statue_build": "Tukora Statue",
"well_build": "Tukora Well"
}
},
"party": {
"newpartyview": {
"open": "Create New Party",
"close": "Hide New Party",
"type": "Party Type"
},
"music": {
"label": "Musika",
"none": "No Musika",
"bard": "A Bard",
"villageBand": "A Village Band",
"chamberOrchestra": "A Chamber Orchestra",
"symphonyOrchestra": "A Symphony Orchestra",
"symphonyOrchestraWithChorusAndSolists": "A Symphony Orchestra uban sa Chorus ug Soloists"
},
"banquette": {
"label": "Pagkaon",
"bread": "Pan",
"roastWithBeer": "Roast uban sa Beer",
"poultryWithVegetablesAndWine": "Poultry uban sa Vegetables ug Wine",
"extensiveBuffet": "Festive Meal"
},
"servants": {
"label": "One sulugoon per ",
"perPersons": " persons"
},
"esteemedInvites": {
"label": "Invited Estates"
},
"type": "Party Type",
"cost": "Kantidad",
"date": "Petsa"
}
},
"underground": {
"activities": {
"additionalInfo": "Additional information",
"blackmailAmount": "Blackmail amount",
"discoveries": "Discoveries",
"visibilityDelta": "Visibility",
"reputationDelta": "Dungog",
"victimPlaceholder": "Enter username",
"sabotageTarget": "Sabotage target",
"corruptGoal": "Corruption goal",
"affairGoal": "Investigation goal",
"raidRegion": "Raid rehiyon",
"raidRegionPlaceholder": "Select rehiyon",
"bandSize": "Band size",
"raidSummary": "Gang ({bandSize}) sa {rehiyon}",
"attempts": "Attempts",
"successes": "Malampusones",
"lastOutcome": "Last outcome",
"raidResultTitle": "Latest raid",
"lastTargetTransport": "Latest target transport",
"loot": "Bilin"
},
"types": {
"spyin": "Espiya",
"assassin": "Assassination",
"sabotage": "Sabotage",
"corrupt_politician": "Corruption",
"rob": "Kawat",
"investigate_affair": "Investigate uyab",
"raid_transport": "Raid transports"
},
"targets": {
"house": "Balay",
"storage": "Tipigan"
},
"goals": {
"elect": "Appointment",
"taxIncrease": "Raise buhises",
"taxDecrease": "Lower buhises",
"expose": "Expose",
"blackmail": "Blackmail"
},
"status": {
"pending": "Naghuwat",
"resolved": "Nasulbad",
"failed": "Napakyas"
},
"raidOutcomes": {
"repelled": "Repelled",
"partial_success": "Partial success",
"major_success": "Major success"
}
}
}
}

View File

@@ -0,0 +1,386 @@
{
"socialnetwork": {
"profile": {
"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"
},
"forum": {
"pagination": {
"first": "Unang panid",
"previous": "Miaging panid",
"next": "Sunod nga panid",
"last": "Kataposang panid",
"page": "Panid <<page>> sa <<of>>"
}
},
"erotic": {
"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."
}
}
},
"vocab": {
"title": "Trainer sa bokabularyo",
"description": "Paghimo og pinulongans (or subscribe aron them) ug share them uban sa friends.",
"newLanguage": "New pinulongan",
"newLanguageTitle": "Paghimo og new pinulongan",
"languageName": "Pinulongan name",
"create": "Paghimo",
"saving": "Saving...",
"created": "Pinulongan created.",
"createdTitle": "Trainer sa bokabularyo",
"createdMessage": "Pinulongan created. Ang menu will refresh.",
"createError": "Dili ma create pinulongan.",
"openLanguage": "Ablihi",
"none": "Ikaw naay no pinulongans yet (created o subscribed).",
"owner": "Owned",
"subscribed": "Mag-subscribed",
"languageTitle": "Trainer sa bokabularyo: {name}",
"notFound": "Pinulongan not found o no access.",
"shareCode": "Ipaambit code",
"shareHint": "Padal-a ang kini nga code aron friends so they can subscribe aron kini nga pinulongan.",
"subscribeByCode": "Mag-subscribe by code",
"subscribeTitle": "Mag-subscribe aron pinulongan",
"subscribeHint": "Enter a share code you received gikan sa a friend.",
"subscribe": "Mag-subscribe",
"subscribeSuccess": "Mag-subscribed. Ang menu will refresh.",
"subscribeError": "Mag-subscribe failed. Dili balido code o no access.",
"trainerPlaceholder": "Trainer features (words/quizzes) will be ang next step.",
"chapters": "Kapitulos",
"newChapter": "New kapitulo",
"createChapter": "Paghimo og kapitulo",
"createChapterError": "Dili ma create kapitulo.",
"noChapters": "Walay kapitulos yet.",
"chapterTitle": "Kapitulo: {title}",
"addVocab": "Add bokabularyo",
"learningWord": "To learn",
"referenceWord": "Reference",
"add": "Add",
"addVocabError": "Dili ma add bokabularyo.",
"noVocabs": "Walay bokabularyo sa kini nga kapitulo yet.",
"practice": {
"open": "Praktis",
"title": "Praktis bokabularyo",
"allVocabs": "Tanan nga bokabularyo",
"simple": "Simple praktis",
"noPool": "Walay bokabularyo aron praktis.",
"dirLearningToRef": "To learn → Reference",
"dirRefToLearning": "Reference → To learn",
"check": "Susihi",
"next": "Sunod",
"skip": "Laktaw",
"correct": "Tama!",
"wrong": "Sayop.",
"acceptable": "Acceptable answers:",
"stats": "Stats",
"success": "Malampuson",
"fail": "Fail"
},
"search": {
"open": "Pangita",
"title": "Pangita bokabularyo",
"term": "Pangita term",
"motherTongue": "Pinulongan nga inahan",
"learningLanguage": "Pagkat-on pinulongan",
"lesson": "Leksiyon",
"search": "Pangita",
"noResults": "Walay results.",
"error": "Pangita failed."
},
"courses": {
"title": "Pinulongan Pagkat-on Kursos",
"create": "Paghimo og Kurso",
"myCourses": "My Kursos",
"allCourses": "Tanan nga Kursos",
"none": "Walay kursos found.",
"owner": "Tag-iya",
"enrolled": "Na-enroll",
"public": "Publiko",
"difficulty": "Kalisod",
"lessons": "Leksiyons",
"enroll": "Enroll",
"continue": "Padayon",
"edit": "Edit",
"addLesson": "Add Leksiyon",
"completed": "Nahuman",
"score": "Score",
"review": "Balik-balik",
"start": "Sugdi",
"noLessons": "Kini nga kurso naay no leksiyons yet.",
"lessonNumber": "Leksiyon Number",
"chapter": "Kapitulo",
"selectChapter": "Select Kapitulo",
"selectLanguage": "Select Pinulongan",
"confirmDelete": "Tinuod nga delete leksiyon?",
"titleLabel": "Titulo",
"descriptionLabel": "Deskripsiyon",
"languageLabel": "Pinulongan",
"findByCode": "Find Kurso by Code",
"shareCode": "Ipaambit Code",
"searchPlaceholder": "Pangita kursos...",
"allLanguages": "Tanan nga Pinulongans",
"targetLanguage": "Target Pinulongan",
"nativeLanguage": "Native Pinulongan",
"allNativeLanguages": "Tanan nga Native Pinulongans",
"myNativeLanguage": "My Native Pinulongan",
"forAllLanguages": "For Tanan nga Pinulongans",
"optional": "Opsyonal",
"invalidCode": "Dili balido code",
"courseNotFound": "Kurso not found",
"grammarExercises": "Tsek sa kapitulo",
"exerciseFlowIntro": "Work through ang tasks sa order. Every tama answer moves you closer aron completing ang leksiyon.",
"exerciseProgressLabel": "Progress",
"exerciseTargetLabel": "Required",
"exerciseCardLabel": "Task {number}",
"exerciseSequentialProgress": "Question {current} sa {total}",
"exerciseSequentialBack": "Balik",
"exerciseSequentialNext": "Sunod",
"exerciseWrongTitle": "Dili quite right",
"exerciseReinforcementGoPractice": "Go aron praktis",
"exerciseReinforcementStay": "Stay sa ang test",
"exerciseReinforcementGoPracticeAck": "Read, go aron praktis",
"exerciseReinforcementStayAck": "Read, stay sa ang test",
"exerciseStatusOpen": "Ablihi",
"exerciseStatusCorrect": "Done",
"exerciseStatusRetry": "Try again",
"exerciseAnswerAllHint": "Answer tanan nga {total} tasks una. Nahuman so far: {answered}. Ikaw need sa least {target}% aron pass.",
"exerciseNeedMoreCorrectHint": "Ikaw currently naay {score}%. Ikaw need sa least {target}% aron complete kini nga leksiyon.",
"exercisePassedHint": "Target reached: {score}% out sa ang required {target}%. Once tanan nga tasks naay been answered, ang tsek sa kapitulo is passed.",
"exerciseReinforcementHint": "After a mistake, ang flow returns briefly aron pagkat-on mode. Praktis {count} more trainer questions ug ang tsek sa kapitulo will unlock again.",
"exercisePrepReinforcementHint": "After a mistake, go through ang prepared terms once more. Then ang tsek sa kapitulo will unlock again.",
"exerciseGrammarLead": "Key grammar para sa kini nga test",
"noExercises": "Walay test available",
"enterAnswer": "Enter answer",
"checkAnswer": "Susihi Answer",
"correct": "Tama!",
"wrong": "Sayop",
"explanation": "Pasabot",
"learn": "Learn",
"exercises": "Tsek sa kapitulo",
"learnVocabulary": "Learn Bokabularyo",
"lessonOverviewText": "Kini nga leksiyon combines bokabularyo, patterns, short grammar impulses, ug active speaking praktis.",
"lessonDescription": "Leksiyon Deskripsiyon",
"culturalNotes": "Cultural Notes",
"grammarExplanations": "Gramatika Pasabots",
"grammarImpulse": "Gramatika Focus",
"learningGoals": "Pagkat-on Goals",
"corePatterns": "Core Patterns",
"corePatternsHint": "Read ang target pinulongan una, then ang meaning below — you learn each pattern both ways.",
"learningGrammarTitle": "Briefly frame ang grammar",
"learningGrammarIntro": "Read these 1-2 hints human sa ang key terms. Then you go into ang trainer uban sa better orientation.",
"vocabPrepTitle": "Preparation sa wala pa ang bokabularyo trainer",
"vocabPrepStep1": "Read through core patterns ug ang word list (native pinulongan ↔ target pinulongan) once.",
"vocabPrepProgress": "Pass {pass}: item {current} sa {total}",
"vocabPrepTargetLabel": "Target pinulongan",
"vocabPrepGlossLabel": "Meaning",
"vocabPrepNextItem": "Sunod item",
"vocabPrepConfirm1": "Una pass done",
"vocabPrepStep2": "Go through ang same items again (active review, not testing yet).",
"vocabPrepConfirm2": "Second pass done",
"vocabPrepReady": "Ikaw can start ang bokabularyo trainer now.",
"learningPathLabel": "Main path",
"learningPathTitle": "Your pagkat-on flow para sa kini nga leksiyon",
"learningPathIntro": "Work through these steps sa order: prepare, review briefly, train, then move aron ang tsek sa kapitulo.",
"lessonDetailsToggle": "Show more leksiyon details",
"deepenSectionTitle": "Deepen ug review",
"assistantSectionTitle": "Deepen uban sa pinulongan katabang",
"vocabOverviewToggle": "Show full overview sa terms",
"vocabTrainerLockedHint": "Palihog confirm two preparation steps under “Preparation sa wala pa ang bokabularyo trainer” una.",
"exerciseUnlockHintAfterPrep": "Work through ang prepared terms una. Ang tsek sa kapitulo will unlock afterwards.",
"speakingTasks": "Speaking Tasks",
"speakingPrompt": "Speaking Prompt",
"practicalTasks": "Practical Tasks",
"importantVocab": "Important Bokabularyo",
"vocabInfoText": "These terms are used sa ang test. Learn them here passively sa wala pa switching aron ang tsek sa kapitulo.",
"noVocabInfo": "Read ang description above ug ang pasabots sa ang test aron learn ang most important terms.",
"vocabTrainer": "Bokabularyo Trainer",
"vocabTrainerDescription": "Praktis ang most important terms sa kini nga leksiyon interactively.",
"startVocabTrainer": "Sugdi ang Bokabularyo Trainer",
"stopTrainer": "Hunong ang Trainer",
"translateTo": "Translate into Bisaya",
"translateFrom": "Translate into German",
"next": "Sunod",
"totalAttempts": "Attempts",
"successRate": "Malampuson Rate",
"modeMultipleChoice": "Multiple Choice",
"modeTyping": "Text Input",
"currentLesson": "Current Leksiyon",
"mixedReview": "Balik-balik",
"lessonCompleted": "Leksiyon completed!",
"goToNextLesson": "Go aron next leksiyon?",
"allLessonsCompleted": "Tanan nga leksiyons completed!",
"startExercises": "Sugdi ang Tsek sa kapitulo",
"lessonTypeLabel": "Leksiyon Type",
"recommendedDuration": "Recommended Duration",
"exerciseLoad": "Exercise Load",
"exercisesShort": "exercises",
"durationFlexible": "Flexible",
"durationMinutes": "{ka minuto} ka minuto",
"lessonTypeVocab": "Bokabularyo",
"lessonTypeGrammar": "Gramatika",
"lessonTypeConversation": "Panag-istoryahanay",
"lessonTypeCulture": "Kultura",
"lessonTypeReview": "Balik-balik",
"correctAnswer": "Tama Answer",
"alternatives": "Alternative Answers",
"notStarted": "Dili Sugdied",
"continueCurrentLesson": "Padayon Current Leksiyon",
"previousLessonRequired": "Palihog complete ang previous leksiyon una",
"lessonNumberShort": "#",
"buildSentencePlaceholder": "Build imong sentence here",
"completeDialogPlaceholder": "Complete ang missing dialog line",
"situationalResponsePlaceholder": "Write imong response aron ang situation",
"patternDrillPlaceholder": "Paghimo og a fitting sentence uban sa ang pattern",
"modelSentence": "Model sentence",
"modelDialogLine": "Possible dialog line",
"modelResponse": "Possible response",
"modelPattern": "Possible pattern example",
"patternPrompt": "Pattern",
"readingAloudInstruction": "Read ang text aloud. Click 'Sugdi ang Nagrekord' ug begin speaking.",
"speakingFromMemoryInstruction": "Speak freely gikan sa memory. Use ang displayed keywords.",
"startRecording": "Sugdi ang Nagrekord",
"stopRecording": "Hunong ang Nagrekord",
"startSpeaking": "Sugdi ang Speaking",
"recording": "Nagrekord...",
"listening": "Listening...",
"recordingStopped": "Nagrekord stopped",
"recordingError": "Nagrekord error",
"recognizedText": "Recognized Text",
"speechRecognitionNotSupported": "Speech Recognition is not supported by kini nga browser. Palihog use Chrome o Edge.",
"speakingFallbackInstruction": "Your browser does not support speech input here. Write down what you would say instead ug check it normally.",
"speakingFallbackPlaceholder": "Write what you would say here ...",
"keywords": "Keywords",
"switchBackToMultipleChoice": "Switch back aron Multiple Choice",
"languageAssistantEyebrow": "Pinulongan katabang",
"languageAssistantCourseTitle": "AI support para sa kini nga kurso",
"languageAssistantCourseReady": "Ang pinulongan katabang is configured ug available inside leksiyons para sa pasabots, tamaions, ug short dialogue praktis.",
"languageAssistantCourseSetup": "Set up ang pinulongan katabang so you can ask leksiyon-specific questions ug praktis short dialogues.",
"languageAssistantOpenLesson": "Ablihi ang sa current leksiyon",
"languageAssistantTitle": "Praktis uban sa ang pinulongan katabang",
"languageAssistantIntro": "Use ang AI directly inside ang current leksiyon: get grammar explained, praktis short dialogues, o naay imong own sentences tamaed.",
"languageAssistantSettings": "Configure katabang",
"languageAssistantSetupHint": "Ang pinulongan katabang is not configured yet o is currently disabled. Palihog save imong model ug API access sa ang settings una.",
"languageAssistantModePractice": "Praktis",
"languageAssistantModeExplain": "Explain",
"languageAssistantModeCorrect": "Tama",
"languageAssistantPromptExplain": "Explain grammar",
"languageAssistantPromptPractice": "Praktis mini dialogue",
"languageAssistantPromptCorrect": "Improve my sentence",
"languageAssistantSpeakerAi": "Pinulongan katabang",
"languageAssistantSpeakerYou": "You",
"languageAssistantInputLabel": "Your mensahe",
"languageAssistantInputPlaceholder": "Ask a leksiyon question o write imong own sentence para sa tamaion.",
"languageAssistantSend": "Padal-a ang aron katabang",
"languageAssistantSending": "Getting answer ...",
"languageAssistantError": "Ang pinulongan katabang could not answer right now.",
"languageAssistantPresetExplainStart": "Palihog explain ang main patterns ug grammar sa ang leksiyon",
"languageAssistantPatternHint": "Focus especially sa kini nga pattern",
"languageAssistantPresetPracticeStart": "Let's praktis a short everyday dialogue para sa ang leksiyon \"{leksiyon}\". Palihog ask me questions ug wait para sa my answers.",
"languageAssistantPresetCorrectStart": "I want aron write my own sentences para sa ang leksiyon \"{leksiyon}\". Palihog tama my answers briefly ug clearly.",
"thisLesson": "this leksiyon",
"quickReviewTitle": "Quick Balik-balik",
"quickReviewIntro": "Short session uban sa {count} terms. After completion, ang scheduled review is marked as done.",
"quickReviewDoneTitle": "Done",
"quickReviewDoneScore": "Tama: {tama} / {total}",
"quickReviewBackToCourse": "Balik aron kurso",
"quickReviewProgress": "Term {current} sa {total}",
"quickReviewPromptMeaning": "What does \"{term}\" mean?",
"quickReviewPromptTarget": "Type sa target pinulongan: \"{term}\"",
"quickReviewAcknowledge": "Read, continue",
"courseTodayPlanIntroNoDueReview": "Walay quick review is due today. Sugdi ang uban sa ang open leksiyons sa imong current block, then do intensive review if shown. Quick reviews reappear automatically sa ang 1/3/7-day rhythm."
}
}
}
}

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env node
/**
* Tiefes Zusammenführen eines Patch-Objekts in eine Ceb-Locale-Datei.
* Nutzung: node merge-ceb-locale-patch.mjs <ziel.json> <patch.json>
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
function isPlainObject(value) {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}
function deepMerge(target, source) {
if (!isPlainObject(source)) return target;
const base = isPlainObject(target) ? { ...target } : {};
for (const key of Object.keys(source)) {
const sv = source[key];
const tv = base[key];
if (isPlainObject(sv) && isPlainObject(tv)) {
base[key] = deepMerge(tv, sv);
} else if (isPlainObject(sv)) {
base[key] = deepMerge({}, sv);
} else {
base[key] = sv;
}
}
return base;
}
const targetPath = path.resolve(process.argv[2] || '');
const patchPath = path.resolve(process.argv[3] || '');
if (!targetPath || !patchPath || !fs.existsSync(targetPath) || !fs.existsSync(patchPath)) {
console.error('Usage: node merge-ceb-locale-patch.mjs <target.json> <patch.json>');
process.exit(1);
}
const base = JSON.parse(fs.readFileSync(targetPath, 'utf8'));
const patch = JSON.parse(fs.readFileSync(patchPath, 'utf8'));
const merged = deepMerge(base, patch);
fs.writeFileSync(targetPath, JSON.stringify(merged, null, 4) + '\n', 'utf8');
console.log('Merged patch into', targetPath);