🌉 fix: Preserve Missing Locize Translations (#14917)

This commit is contained in:
Danny Avila 2026-08-17 02:20:25 -04:00 committed by GitHub
parent 57ea1137f6
commit c77e6a5ad2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 100 additions and 3 deletions

View file

@ -2,11 +2,12 @@ name: Sync Locize Translations & Create Translation PR
on:
push:
branches: [main]
branches: [dev]
paths:
- 'client/src/locales/en/**'
repository_dispatch:
types: [locize/versionPublished]
workflow_dispatch:
concurrency:
group: locize-i18n-sync
@ -51,7 +52,7 @@ jobs:
create-pull-request:
name: Create Translation PR on Version Published
if: ${{ github.event_name == 'repository_dispatch' }}
if: ${{ github.event_name == 'repository_dispatch' || github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-latest
needs: sync-translations
permissions:
@ -61,6 +62,7 @@ jobs:
- name: Checkout Repository
uses: actions/checkout@v5
with:
ref: dev
persist-credentials: false
# Keep a baseline so generated changes can be checked before opening a PR.
@ -75,6 +77,12 @@ jobs:
path: "client/src/locales"
version: latest
- name: Preserve Repository Translations Missing from locize
run: |
node scripts/merge-locize-download.mjs \
--base-dir "$RUNNER_TEMP/locize-locale-baseline" \
--current-dir client/src/locales
- name: Validate Downloaded Translations
run: |
node scripts/validate-locize-download.mjs \
@ -91,7 +99,7 @@ jobs:
add-paths: |
client/src/locales/**
commit-message: "🌍 i18n: Update translation.json with latest translations"
base: main
base: dev
branch: i18n/locize-translation-update
title: "🌍 i18n: Update translation.json with latest translations"
body: |

View file

@ -0,0 +1,89 @@
#!/usr/bin/env node
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
const args = new Map();
for (let index = 2; index < process.argv.length; index += 1) {
if (!process.argv[index].startsWith('--')) continue;
args.set(process.argv[index].slice(2), process.argv[index + 1]);
index += 1;
}
const baseDir = args.get('base-dir');
const currentDir = args.get('current-dir');
if (!baseDir || !currentDir) {
console.error('Usage: merge-locize-download.mjs --base-dir <path> --current-dir <path>');
process.exit(2);
}
function isObject(value) {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}
function leafCount(value) {
if (!isObject(value)) return 1;
return Object.values(value).reduce((count, child) => count + leafCount(child), 0);
}
function mergeValues(base, current) {
if (!isObject(base) || !isObject(current)) return { value: current, restored: 0 };
let restored = 0;
const value = {};
for (const [key, baseValue] of Object.entries(base)) {
if (!Object.hasOwn(current, key)) {
value[key] = baseValue;
restored += leafCount(baseValue);
continue;
}
const merged = mergeValues(baseValue, current[key]);
value[key] = merged.value;
restored += merged.restored;
}
for (const [key, currentValue] of Object.entries(current)) {
if (!Object.hasOwn(base, key)) value[key] = currentValue;
}
return { value, restored };
}
async function jsonFiles(directory, relative = '') {
const entries = await readdir(path.join(directory, relative), { withFileTypes: true });
const files = [];
for (const entry of entries) {
const entryRelative = path.join(relative, entry.name);
if (entry.isDirectory()) files.push(...(await jsonFiles(directory, entryRelative)));
else if (entry.isFile() && entry.name.endsWith('.json')) files.push(entryRelative);
}
return files;
}
async function readJson(filePath) {
return JSON.parse(await readFile(filePath, 'utf8'));
}
let restored = 0;
let changedFiles = 0;
for (const relative of await jsonFiles(baseDir)) {
const basePath = path.join(baseDir, relative);
const currentPath = path.join(currentDir, relative);
const base = await readJson(basePath);
let current;
try {
current = await readJson(currentPath);
} catch (error) {
if (error.code !== 'ENOENT') throw error;
current = {};
}
const merged = mergeValues(base, current);
if (merged.restored === 0) continue;
await mkdir(path.dirname(currentPath), { recursive: true });
await writeFile(currentPath, `${JSON.stringify(merged.value, null, 2)}\n`);
restored += merged.restored;
changedFiles += 1;
}
console.log(`Preserved ${restored} repository translation value(s) across ${changedFiles} file(s).`);