diff --git a/.github/workflows/i18n-update-core.yaml b/.github/workflows/i18n-update-core.yaml index 5f0985b93..38898f014 100644 --- a/.github/workflows/i18n-update-core.yaml +++ b/.github/workflows/i18n-update-core.yaml @@ -43,7 +43,7 @@ jobs: env: PLAYWRIGHT_TEST_URL: http://localhost:5173 - name: Update translations - run: pnpm locale && pnpm format + run: pnpm locale && pnpm fix-i18n-node-defs && pnpm format env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Commit updated locales diff --git a/.github/workflows/i18n-update-custom-nodes.yaml b/.github/workflows/i18n-update-custom-nodes.yaml index 225c1b3e3..4c6788fad 100644 --- a/.github/workflows/i18n-update-custom-nodes.yaml +++ b/.github/workflows/i18n-update-custom-nodes.yaml @@ -67,7 +67,7 @@ jobs: env: PLAYWRIGHT_TEST_URL: http://localhost:5173 - name: Update translations - run: pnpm locale + run: pnpm locale && pnpm fix-i18n-node-defs env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Diff base vs updated i18n diff --git a/.github/workflows/i18n-update-nodes.yaml b/.github/workflows/i18n-update-nodes.yaml index 5a72e5b10..8c974addb 100644 --- a/.github/workflows/i18n-update-nodes.yaml +++ b/.github/workflows/i18n-update-nodes.yaml @@ -36,7 +36,7 @@ jobs: env: PLAYWRIGHT_TEST_URL: http://localhost:5173 - name: Update translations - run: pnpm locale + run: pnpm locale && pnpm fix-i18n-node-defs env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - name: Create Pull Request diff --git a/package.json b/package.json index 643b3c71a..9181a69b9 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "dev": "nx serve", "devtools:pycheck": "python3 -m compileall -q tools/devtools", "format:check": "oxfmt --check", + "fix-i18n-node-defs": "tsx scripts/fix-i18n-node-defs.ts", "format": "oxfmt --write", "json-schema": "tsx scripts/generate-json-schema.ts", "knip:no-cache": "knip", diff --git a/scripts/fix-i18n-node-defs.ts b/scripts/fix-i18n-node-defs.ts new file mode 100644 index 000000000..569e79be6 --- /dev/null +++ b/scripts/fix-i18n-node-defs.ts @@ -0,0 +1,66 @@ +import { readFileSync, readdirSync, writeFileSync } from 'fs' +import { join } from 'path' + +const LOCALES_DIR = 'src/locales' + +/** + * Convert arrays with numeric indices back to objects. + * GPT-4.1 (used by @lobehub/i18n-cli) sometimes converts + * {"0": {...}, "1": {...}} objects into JSON arrays with null gaps. + */ +function fixArraysToObjects(value: unknown): Record | unknown { + if (!value || typeof value !== 'object') return value + + if (Array.isArray(value)) { + const obj: Record = {} + for (let i = 0; i < value.length; i++) { + if (value[i] != null) { + obj[String(i)] = fixArraysToObjects(value[i]) + } + } + return obj + } + + const record = value as Record + const result: Record = {} + for (const key of Object.keys(record)) { + result[key] = fixArraysToObjects(record[key]) + } + return result +} + +function run() { + const locales = readdirSync(LOCALES_DIR, { withFileTypes: true }) + .filter((d) => d.isDirectory() && d.name !== 'en') + .map((d) => d.name) + + let totalFixes = 0 + + for (const locale of locales) { + const filePath = join(LOCALES_DIR, locale, 'nodeDefs.json') + let raw: string + try { + raw = readFileSync(filePath, 'utf-8') + } catch { + continue + } + + const data = JSON.parse(raw) + const fixed = fixArraysToObjects(data) as Record + const fixedJson = JSON.stringify(fixed, null, 2) + '\n' + + if (fixedJson !== raw) { + writeFileSync(filePath, fixedJson) + totalFixes++ + console.warn(`Fixed: ${filePath}`) + } + } + + if (totalFixes === 0) { + console.warn('No fixes needed') + } else { + console.warn(`Fixed ${totalFixes} file(s)`) + } +} + +run()