Skip to content

Simplify translation workflow to push locale files directly#76

Merged
kilbot merged 5 commits intomainfrom
fix/simplify-translation-workflow
Feb 6, 2026
Merged

Simplify translation workflow to push locale files directly#76
kilbot merged 5 commits intomainfrom
fix/simplify-translation-workflow

Conversation

@kilbot
Copy link
Copy Markdown
Contributor

@kilbot kilbot commented Feb 6, 2026

Summary

  • Workflow now copies the English locale JSON files (core.json, electron.json) straight to the translations-source branch instead of running an extraction script
  • Removes the monorepo setup step from CI (no more pnpm install just to push translation strings)
  • Trigger paths narrowed to only fire when the locale files actually change
  • Migrates apps/main drawer labels from raw English strings to symbolic keys (t('POS') -> t('common.pos'), etc.)
  • Updates extraction script to output clean "key": "value" format (kept as optional local validation tool)

Test plan

  • Verify drawer labels still render correctly in the app
  • Manually trigger the workflow via workflow_dispatch and confirm translations-source branch contains the expected JSON files

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Simplified translation workflow to push two core English locale files and removed prior extraction/setup steps.
    • Updated extraction to produce per-namespace JSONs resolved against English source values, including plural-key handling.
    • Switched drawer navigation labels to use common translation keys.
  • Documentation

    • Added a workflow guide describing the streamlined push/dispatch process.
  • Tests / Style

    • Reformatted translation-related tests with no behavioral changes.

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.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 6, 2026

📝 Walkthrough

Walkthrough

Replaces 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 common.* keys.

Changes

Cohort / File(s) Summary
GitHub Workflow
\.github/workflows/push-js-strings.yml
Renamed job, narrowed path filters to two English locale JSONs, removed setup/extract steps, and replaced the previous copy/dispatch pipeline with creating a temp translations-out dir -> orphan-branch checkout -> copy -> commit -> push flow.
Extraction Script
scripts/extract-js-strings.js
Refactored to collect keys per-namespace (Sets), added LOCALE_FILES mapping and loadLocale, changed extractFromFile to return {key, namespace} entries, preload English locale files, map keys (including plural suffixes) to English values, and emit per-namespace JSON outputs.
App Drawer Localization
apps/main/app/(app)/(drawer)/_layout.tsx
Replaced explicit per-item translation keys (e.g., POS, Products, Orders, Customers, Reports, Logs, Support) with generic common.* keys for titles and drawer labels; icons and structure unchanged.
Docs
.github/TRANSLATION_WORKFLOW.md
New documentation describing the simplified push workflow, required secrets (TRANSLATION_APP_ID, TRANSLATION_APP_PRIVATE_KEY), and a template for pushing English locale files to a translations repository.
Tests / Formatting
packages/core/src/contexts/translations/rxdb-backend.test.ts
Stylistic/formatting edits only (line breaks/indentation); no behavioral changes.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through keys and JSON seas,
I sniffed core and electron trees,
Gathered namespaces, one by one,
Packed them up and pushed that branch — hop, done! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective of the pull request: simplifying the translation workflow to push locale files directly instead of running extraction scripts.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/simplify-translation-workflow

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 6, 2026

🚀 Deployment Summary

Item Status
Preview URL https://wcpos--3w8ul5e0o0.expo.app
E2E Tests ❌ Failed
Commit ddde0f8

🔗 Quick Links

❌ Failed Tests (4 total)

settings.spec.ts

  • [free-authenticated] should change language to French and load translations from CDN

    Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

  • [free-authenticated] should persist language after closing and reopening settings

    Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

  • [pro-authenticated] should change language to French and load translations from CDN

    Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed
    ...and 1 more in this file

📋 Full error details (first 5)

settings.spec.ts - should change language to French and load translations from CDN

Project: free-authenticated

Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: getByText('Produit')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for getByText('Produit')�[22m

settings.spec.ts - should persist language after closing and reopening settings

Project: free-authenticated

Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: getByText('Produit')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for getByText('Produit')�[22m

settings.spec.ts - should change language to French and load translations from CDN

Project: pro-authenticated

Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: getByText('Produit')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for getByText('Produit')�[22m

settings.spec.ts - should persist language after closing and reopening settings

Project: pro-authenticated

Error: �[2mexpect(�[22m�[31mlocator�[39m�[2m).�[22mtoBeVisible�[2m(�[22m�[2m)�[22m failed

Locator: getByText('Produit')
Expected: visible
Timeout: 15000ms
Error: element(s) not found

Call log:
�[2m  - Expect "toBeVisible" with timeout 15000ms�[22m
�[2m  - waiting for getByText('Produit')�[22m

📸 Failure Screenshots

📷 settings Language Settings 2a494 sing and reopening settings free authenticated

settings Language Settings 2a494 sing and reopening settings free authenticated

📷 settings Language Settings 2a494 sing and reopening settings free authenticated

settings Language Settings 2a494 sing and reopening settings free authenticated

📷 settings Language Settings 53f0f load translations from CDN free authenticated

settings Language Settings 53f0f  load translations from CDN free authenticated

📷 settings Language Settings 53f0f load translations from CDN free authenticated

settings Language Settings 53f0f  load translations from CDN free authenticated

📷 settings Language Settings 53f0f load translations from CDN pro authenticated

settings Language Settings 53f0f  load translations from CDN pro authenticated

📷 settings Language Settings 53f0f load translations from CDN pro authenticated

settings Language Settings 53f0f  load translations from CDN pro authenticated

🔗 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
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 6, 2026

📊 Test Coverage Report

Package Statements Branches Functions Lines
@wcpos/core 🔴 37.5% 🔴 44.0% 🔴 43.2% 🔴 36.2%
@wcpos/components 🔴 44.9% 🟡 60.9% 🔴 24.2% 🔴 47.3%
@wcpos/database 🔴 33.2% 🔴 35.9% 🔴 40.3% 🔴 32.9%
@wcpos/hooks 🔴 45.5% 🔴 46.8% 🔴 44.8% 🔴 45.7%
@wcpos/utils 🔴 35.0% 🔴 0.0% 🔴 50.0% 🔴 33.3%
@wcpos/query 🟡 68.0% 🔴 52.6% 🟡 66.1% 🟡 68.0%
Average 🔴 44.0% 🔴 40.0% 🔴 44.7% 🔴 43.9%
Coverage Legend
  • 🟢 Good (≥80%)
  • 🟡 Moderate (60-79%)
  • 🔴 Needs improvement (<60%)
  • ⚪ No coverage data
--- 🤖 Updated by GitHub Actions • [View full report](https://github.com/wcpos/monorepo/actions/runs/21759333089)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@kilbot kilbot merged commit 0ccbfac into main Feb 6, 2026
3 of 4 checks passed
@kilbot kilbot deleted the fix/simplify-translation-workflow branch February 6, 2026 17:19
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +65 to +72
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 {};
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

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.

@kilbot kilbot restored the fix/simplify-translation-workflow branch February 6, 2026 17:34
@kilbot kilbot deleted the fix/simplify-translation-workflow branch February 6, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant