Simplify translation workflow to push locale files directly#76
Conversation
Instead of extracting t() keys from source and building an intermediate format, push the English locale JSON files straight to the translations repo. Also migrates apps/main drawer labels to symbolic translation keys.
📝 WalkthroughWalkthroughReplaces the previous extraction-and-dispatch workflow with a simplified push workflow that directly collects two English locale JSONs and pushes them on an orphan translations branch; refactors the extraction script to aggregate keys by namespace and resolve English values from per-namespace locale files; swaps explicit drawer labels to Changes
Sequence DiagramsequenceDiagram
participant WF as "GitHub Workflow"
participant Repo as "Repository (checkout / push)"
participant Script as "extract-js-strings.js"
participant Locale as "English locale JSONs"
participant Out as "translations-out (temp dir)"
WF->>Repo: Checkout source
WF->>Script: Run extraction script
Script->>Locale: Load `core.json` & `electron.json`
Locale-->>Script: Return English translations
Script->>Script: Scan source files, aggregate keys by namespace
Script->>Script: Resolve keys -> English values (handle plural suffixes)
Script->>Out: Write per-namespace JSON files
WF->>Repo: Create orphan translations branch (checkout & clear)
WF->>Out: Copy collected JSONs into branch
WF->>Repo: Commit & push translations branch
WF->>Repo: Dispatch to translations repo using app token
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@scripts/extract-js-strings.js`:
- Around line 125-155: Before writing namespace files, remove any stale files by
deleting and recreating OUTPUT_DIR: call await fs.rmdir(OUTPUT_DIR, { recursive:
true }) inside a try/catch (ignore ENOENT) and then await fs.mkdir(OUTPUT_DIR, {
recursive: true }) before iterating over byNamespace; this ensures old <ns>.json
files are cleared even for namespaces that no longer exist and uses fs.rmdir for
broader Node compatibility with the existing await fs.mkdir usage.
🚀 Deployment Summary
🔗 Quick Links❌ Failed Tests (4 total)settings.spec.ts
📋 Full error details (first 5)settings.spec.ts - should change language to French and load translations from CDNProject: settings.spec.ts - should persist language after closing and reopening settingsProject: settings.spec.ts - should change language to French and load translations from CDNProject: settings.spec.ts - should persist language after closing and reopening settingsProject: 📸 Failure Screenshots🔗 Debug Links
🤖 Updated by GitHub Actions |
- Remove and recreate .translations/ before writing namespace files so stale JSON files from removed namespaces don't linger - Add .github/TRANSLATION_WORKFLOW.md with instructions for other repos
📊 Test Coverage Report
Coverage Legend
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@scripts/extract-js-strings.js`:
- Around line 134-151: The loop currently only collects plural variants when the
base key is missing; change the logic in the for (const key of [...keys].sort())
block so that you always iterate pluralSuffixes
(['_zero','_one','_two','_few','_many','_other']) and copy any
locale[`${key}${suffix}`] into output regardless of whether locale[key] exists;
only emit the warning and increment warnings when neither the base key nor any
plural variant was found. Update references in this block (keys, locale, output,
pluralSuffixes, foundPlural, ns, warnings) so plural detection runs
unconditionally and warning logic checks both base and foundPlural before
logging.
Plural suffixes (_one, _other, etc.) are now checked unconditionally so they aren't dropped when a base key also exists in the locale.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@scripts/extract-js-strings.js`:
- Around line 65-72: The loadLocale function currently swallows all read/parse
errors and returns {}, which hides malformed JSON; change loadLocale to only
tolerate a missing file (err.code === 'ENOENT' -> return {}), but for other
errors (especially JSON.parse errors) rethrow or bubble the error so the process
fails fast; update the catch in loadLocale to check err.code and return {} for
missing files, otherwise throw the error (or call next-level error handling) so
malformed JSON does not silently continue.
| async function loadLocale(filePath) { | ||
| try { | ||
| const content = await fs.readFile(filePath, 'utf8'); | ||
| return JSON.parse(content); | ||
| } catch (err) { | ||
| console.warn(` Warning: could not load locale file ${filePath}: ${err.message}`); | ||
| return {}; | ||
| } |
There was a problem hiding this comment.
Don’t silently continue on malformed locale JSON.
Returning {} on JSON parse errors can produce empty outputs and a false “success” run. Consider failing fast for parse errors while still tolerating a missing file if that’s intended.
🔧 Suggested fix
async function loadLocale(filePath) {
try {
const content = await fs.readFile(filePath, 'utf8');
return JSON.parse(content);
} catch (err) {
- console.warn(` Warning: could not load locale file ${filePath}: ${err.message}`);
- return {};
+ if (err.code === 'ENOENT') {
+ console.warn(` Warning: could not load locale file ${filePath}: ${err.message}`);
+ return {};
+ }
+ throw err;
}
}🤖 Prompt for AI Agents
In `@scripts/extract-js-strings.js` around lines 65 - 72, The loadLocale function
currently swallows all read/parse errors and returns {}, which hides malformed
JSON; change loadLocale to only tolerate a missing file (err.code === 'ENOENT'
-> return {}), but for other errors (especially JSON.parse errors) rethrow or
bubble the error so the process fails fast; update the catch in loadLocale to
check err.code and return {} for missing files, otherwise throw the error (or
call next-level error handling) so malformed JSON does not silently continue.






Summary
core.json,electron.json) straight to thetranslations-sourcebranch instead of running an extraction scriptpnpm installjust to push translation strings)apps/maindrawer labels from raw English strings to symbolic keys (t('POS')->t('common.pos'), etc.)"key": "value"format (kept as optional local validation tool)Test plan
workflow_dispatchand confirmtranslations-sourcebranch contains the expected JSON files🤖 Generated with Claude Code
Summary by CodeRabbit
Chores
Documentation
Tests / Style