Skip to content

Commit 2ee72d3

Browse files
Merge pull request #1574 from objectstack-ai/codex/metadata-form-i18n
Fix Studio metadata form i18n coverage
2 parents e9032ad + d72d15c commit 2ee72d3

12 files changed

Lines changed: 1790 additions & 183 deletions

packages/cli/src/utils/i18n-coverage.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,7 @@ function walkMetadataFormField(field: any, type: string, parentPath: string, out
259259
const name = typeof field.field === 'string' ? field.field : undefined;
260260
const path = name ? (parentPath ? `${parentPath}.${name}` : name) : parentPath;
261261
if (path) {
262-
if (typeof field.label === 'string' && field.label.length > 0) {
263-
pushKey(out, ['metadataForms', type, 'fields', path, 'label'], 'metadataForm', `Metadata form ${type}.fields.${path} label`);
264-
}
262+
pushKey(out, ['metadataForms', type, 'fields', path, 'label'], 'metadataForm', `Metadata form ${type}.fields.${path} label`);
265263
if (typeof field.helpText === 'string' && field.helpText.length > 0) {
266264
pushKey(out, ['metadataForms', type, 'fields', path, 'helpText'], 'metadataForm', `Metadata form ${type}.fields.${path} helpText`);
267265
}

packages/cli/src/utils/i18n-extract.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,10 @@ function walkFormField(field: any, type: string, parentPath: string, out: Expect
356356
const name = typeof field.field === 'string' ? field.field : undefined;
357357
const path = name ? (parentPath ? `${parentPath}.${name}` : name) : parentPath;
358358
if (path) {
359-
if (typeof field.label === 'string' && field.label.length > 0) {
360-
pushEntry(out, ['metadataForms', type, 'fields', path, 'label'], field.label, 'metadataFormField', { metadataType: type });
361-
}
359+
const label = typeof field.label === 'string' && field.label.length > 0
360+
? field.label
361+
: humanizeFieldPath(path);
362+
pushEntry(out, ['metadataForms', type, 'fields', path, 'label'], label, 'metadataFormField', { metadataType: type });
362363
if (typeof field.helpText === 'string' && field.helpText.length > 0) {
363364
pushEntry(out, ['metadataForms', type, 'fields', path, 'helpText'], field.helpText, 'metadataFormField', { metadataType: type });
364365
}
@@ -371,6 +372,15 @@ function walkFormField(field: any, type: string, parentPath: string, out: Expect
371372
}
372373
}
373374

375+
/** Match the metadata form renderer's fallback label for fields without an explicit label. */
376+
function humanizeFieldPath(path: string): string {
377+
const leaf = path.split('.').pop() ?? path;
378+
return leaf
379+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
380+
.replace(/[_-]+/g, ' ')
381+
.replace(/\b\w/g, (c) => c.toUpperCase());
382+
}
383+
374384
/**
375385
* Section-name derivation mirroring `resolveMetadataFormLabels` so the
376386
* extractor emits keys at the exact same paths the resolver looks them up.

packages/cli/test/i18n-coverage.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ describe('computeI18nCoverage', () => {
159159
const objectSources = new Set(['object', 'field', 'option', 'view', 'action', 'globalAction']);
160160
expect(report.issues.filter((i) => objectSources.has(i.source))).toEqual([]);
161161
expect(report.totals.expectedKeys).toBeGreaterThan(0); // metadataForms baseline
162+
expect(report.issues.some((i) => i.key === 'metadataForms.flow.fields.name.label')).toBe(true);
162163
});
163164

164165
it('treats data.object as fallback for view objectName', () => {

packages/cli/test/i18n-extract.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ describe('collectExpectedEntries', () => {
8080
expect(paths).toContain('objects.sys_role._actions.merge.successMessage');
8181
expect(paths).toContain('globalActions.export_csv.label');
8282
expect(paths).toContain('globalActions.export_csv.successMessage');
83+
expect(paths).toContain('metadataForms.flow.fields.name.label');
8384
});
8485

8586
it('carries source values from the schema', () => {
@@ -89,6 +90,7 @@ describe('collectExpectedEntries', () => {
8990
expect(byPath['objects.sys_role.fields.status.options.on']).toBe('On');
9091
expect(byPath['objects.sys_role.fields.kind.options.internal']).toBe('Internal');
9192
expect(byPath['objects.sys_role._actions.merge.label']).toBe('Merge');
93+
expect(byPath['metadataForms.flow.fields.name.label']).toBe('Name');
9294
});
9395
});
9496

0 commit comments

Comments
 (0)