batch: texts.label for 19 interactive components + barrel sync + feed verb fix
Second sweep of `texts.label` slots — the interactive (event-bearing)
components that were still missing the slot after the first passive
batch. Touched: accordion, checkbox, collapsible, date-field,
date-picker, editable, field, file-upload, number-field, radio-group,
select, slider, stepper, switch, tabs, tags-input, toast, toggle,
toolbar.
Each got:
- A `label: '#?components.{kebab}.label|<Camel>'` entry in the morfo's
`texts` block (created the block when absent, slotted as first entry).
- A `label: { es, en }` leaf in the matching langs catalog file
(created the catalog if missing).
Barrel `src/uix/langs/components/index.ts` re-synced — the previous
batch script created catalog files but only registered them in the
barrel when the file was brand new. After two passes some files
weren't being merged. Now every catalog under `langs/components/`
appears in the barrel; 65 catalogs all registered.
feed: fixed A-3.4b — `commit-load-more` was using verb `add` which is
not in `SEMA_VERBS.commit`. Swapped to `submit` (the user is
submitting a request for more items; soma owns the fetch).
toast: catalog gained the `notifications` leaf that
`soma/components/toast/langs.ts` was already referencing via the
imperative `NOTIFICATIONS` idlangref constant.
Audit: PASS 33 → 34. translations:check clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
/**
|
|
|
|
|
* Second pass of texts.label batch — interactive components remaining.
|
|
|
|
|
*/
|
|
|
|
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
|
|
import { join, dirname } from 'node:path';
|
|
|
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
|
|
|
|
|
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
|
|
|
const REPO = join(HERE, '..');
|
|
|
|
|
const MORFO_DIR = join(REPO, 'src', 'uix', 'morfo', 'components');
|
|
|
|
|
const LANGS_DIR = join(REPO, 'src', 'uix', 'langs', 'components');
|
|
|
|
|
|
|
|
|
|
interface Entry {
|
|
|
|
|
kebab: string;
|
|
|
|
|
label: { es: string; en: string };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const BATCH: Entry[] = [
|
|
|
|
|
{ kebab: 'accordion', label: { es: 'Acordeón', en: 'Accordion' } },
|
|
|
|
|
{ kebab: 'checkbox', label: { es: 'Casilla', en: 'Checkbox' } },
|
|
|
|
|
{ kebab: 'collapsible', label: { es: 'Plegable', en: 'Collapsible' } },
|
|
|
|
|
{ kebab: 'date-field', label: { es: 'Campo de fecha', en: 'Date field' } },
|
|
|
|
|
{ kebab: 'date-picker', label: { es: 'Selector de fecha', en: 'Date picker' } },
|
|
|
|
|
{ kebab: 'editable', label: { es: 'Edición inline', en: 'Editable' } },
|
|
|
|
|
{ kebab: 'field', label: { es: 'Campo', en: 'Field' } },
|
|
|
|
|
{ kebab: 'file-upload', label: { es: 'Subida de archivos', en: 'File upload' } },
|
|
|
|
|
{ kebab: 'number-field', label: { es: 'Campo numérico', en: 'Number field' } },
|
|
|
|
|
{ kebab: 'radio-group', label: { es: 'Grupo de radio', en: 'Radio group' } },
|
|
|
|
|
{ kebab: 'select', label: { es: 'Selector', en: 'Select' } },
|
|
|
|
|
{ kebab: 'slider', label: { es: 'Deslizador', en: 'Slider' } },
|
|
|
|
|
{ kebab: 'stepper', label: { es: 'Asistente paso a paso', en: 'Stepper' } },
|
|
|
|
|
{ kebab: 'switch', label: { es: 'Interruptor', en: 'Switch' } },
|
|
|
|
|
{ kebab: 'tabs', label: { es: 'Pestañas', en: 'Tabs' } },
|
|
|
|
|
{ kebab: 'tags-input', label: { es: 'Entrada de etiquetas', en: 'Tags input' } },
|
|
|
|
|
{ kebab: 'toast', label: { es: 'Aviso emergente', en: 'Toast' } },
|
|
|
|
|
{ kebab: 'toggle', label: { es: 'Conmutador', en: 'Toggle' } },
|
|
|
|
|
{ kebab: 'toolbar', label: { es: 'Barra de herramientas', en: 'Toolbar' } }
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
function kebabToCamel(kebab: string): string {
|
|
|
|
|
return kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addLabelToMorfo(kebab: string): boolean {
|
|
|
|
|
const path = join(MORFO_DIR, `${kebab}.ts`);
|
|
|
|
|
const src = readFileSync(path, 'utf8');
|
|
|
|
|
if (src.includes(`#?components.${kebab}.label`)) return false;
|
|
|
|
|
const camel =
|
|
|
|
|
kebab[0].toUpperCase() + kebab.slice(1).replace(/-(.)/g, (_, c) => ' ' + c.toUpperCase());
|
batch: texts.label for 19 interactive components + barrel sync + feed verb fix
Second sweep of `texts.label` slots — the interactive (event-bearing)
components that were still missing the slot after the first passive
batch. Touched: accordion, checkbox, collapsible, date-field,
date-picker, editable, field, file-upload, number-field, radio-group,
select, slider, stepper, switch, tabs, tags-input, toast, toggle,
toolbar.
Each got:
- A `label: '#?components.{kebab}.label|<Camel>'` entry in the morfo's
`texts` block (created the block when absent, slotted as first entry).
- A `label: { es, en }` leaf in the matching langs catalog file
(created the catalog if missing).
Barrel `src/uix/langs/components/index.ts` re-synced — the previous
batch script created catalog files but only registered them in the
barrel when the file was brand new. After two passes some files
weren't being merged. Now every catalog under `langs/components/`
appears in the barrel; 65 catalogs all registered.
feed: fixed A-3.4b — `commit-load-more` was using verb `add` which is
not in `SEMA_VERBS.commit`. Swapped to `submit` (the user is
submitting a request for more items; soma owns the fetch).
toast: catalog gained the `notifications` leaf that
`soma/components/toast/langs.ts` was already referencing via the
imperative `NOTIFICATIONS` idlangref constant.
Audit: PASS 33 → 34. translations:check clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const m = src.match(/^\ttexts:\s*\{/m);
|
|
|
|
|
if (m) {
|
|
|
|
|
const insertAt = m.index! + m[0].length;
|
|
|
|
|
const labelLine = `\n\t\tlabel: '#?components.${kebab}.label|${camel}',`;
|
|
|
|
|
writeFileSync(path, src.slice(0, insertAt) + labelLine + src.slice(insertAt), 'utf8');
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
const scopeEndRe = /\tscope:\s*\[[^\]]+\][^\n]*\n/;
|
|
|
|
|
const sem = src.match(scopeEndRe);
|
|
|
|
|
if (!sem) return false;
|
|
|
|
|
const start = sem.index! + sem[0].length;
|
|
|
|
|
const textsBlock = `\ttexts: {\n\t\tlabel: '#?components.${kebab}.label|${camel}'\n\t},\n`;
|
|
|
|
|
writeFileSync(path, src.slice(0, start) + textsBlock + src.slice(start), 'utf8');
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addLabelToLangs(entry: Entry): boolean {
|
|
|
|
|
const path = join(LANGS_DIR, `${entry.kebab}.ts`);
|
|
|
|
|
const camel = kebabToCamel(entry.kebab);
|
|
|
|
|
let src: string;
|
|
|
|
|
try {
|
|
|
|
|
src = readFileSync(path, 'utf8');
|
|
|
|
|
} catch {
|
|
|
|
|
src = `import type { LangNode } from '$libs/langs';\n\nexport const ${camel}Langs = {\n} satisfies LangNode;\n`;
|
|
|
|
|
writeFileSync(path, src, 'utf8');
|
|
|
|
|
src = readFileSync(path, 'utf8');
|
|
|
|
|
}
|
|
|
|
|
if (/^\s*label:\s*\{/m.test(src)) return false;
|
|
|
|
|
const exportRe = new RegExp(`(export const ${camel}Langs\\s*=\\s*\\{)`);
|
|
|
|
|
const m = src.match(exportRe);
|
|
|
|
|
if (!m) return false;
|
|
|
|
|
const insertAt = m.index! + m[0].length;
|
|
|
|
|
const labelBlock = `\n\tlabel: {\n\t\tes: '${entry.label.es}',\n\t\ten: '${entry.label.en}'\n\t},`;
|
|
|
|
|
writeFileSync(path, src.slice(0, insertAt) + labelBlock + src.slice(insertAt), 'utf8');
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let added = 0;
|
|
|
|
|
for (const entry of BATCH) {
|
|
|
|
|
const m = addLabelToMorfo(entry.kebab);
|
|
|
|
|
const l = addLabelToLangs(entry);
|
|
|
|
|
if (m || l) {
|
|
|
|
|
console.log(`✓ ${entry.kebab}${m ? ' [morfo]' : ''}${l ? ' [langs]' : ''}`);
|
|
|
|
|
added++;
|
|
|
|
|
} else {
|
|
|
|
|
console.log(`- ${entry.kebab}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
console.log(`\nAdded labels to ${added}/${BATCH.length} components.`);
|