Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .agents/skills/churchcrm/locale-ai-translation.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ No API key or external service is required — translations run directly inside

Every new UI string added to ChurchCRM creates a translation gap in 45+ languages. The AI translation system bridges that gap at release time by:

1. Reading empty batch files from `locale/terms/missing/{locale}/*.json` (generated by `npm run locale:missing`)
1. Reading empty batch files from `locale/terms/missing/{locale}/*.json` (generated by `npm run locale:download:missing`)
2. Translating missing values with Claude Code, applying denomination-aware church vocabulary
3. Writing translated values back into the same batch files
Comment on lines 19 to 23
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

This path placeholder uses {locale}, but the batch directories are keyed by POEditor language code (what entry.poEditor maps to and what /locale-translate --locale <code> expects). Recommend updating to locale/terms/missing/{poEditorCode}/*.json to match the actual folder layout.

Copilot uses AI. Check for mistakes.
4. User uploads those files to POEditor (source of truth), then pulls down via `npm run locale:download`
Expand All @@ -33,8 +33,8 @@ Every new UI string added to ChurchCRM creates a translation gap in 45+ language
## Quick Start

```bash
# 1. Regenerate missing terms list
npm run locale:missing
# 1. Download untranslated terms from POEditor
npm run locale:download:missing

# 2. Preview what needs translation
npm run locale:translate:list
Expand Down Expand Up @@ -67,7 +67,7 @@ npm run locale:download

| Script | What it does |
|--------|-------------|
| `npm run locale:missing` | Regenerate missing-terms batch files |
| `npm run locale:download:missing` | Download untranslated terms per locale from POEditor |
| `npm run locale:translate:list` | List locales with untranslated terms |
| `npm run locale:audit` | Show translation coverage report |
| `npm run locale:download` | Pull approved translations from POEditor |
Expand Down
6 changes: 3 additions & 3 deletions .claude/commands/locale-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ Run the full localization pipeline before a release: regenerate missing terms, t

## Steps

### Step 1 — Regenerate missing terms
### Step 1 — Download missing terms from POEditor

```bash
npm run locale:missing
npm run locale:download:missing
```

This compares `locale/messages.json` against all installed `src/locale/i18n/*.json` files and writes fresh empty batch files to `locale/terms/missing/{locale}/`.
This queries POEditor with `filters=untranslated` for each locale and writes fresh empty batch files to `locale/terms/missing/{locale}/`.
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The missing-terms directory name is the POEditor code (the --locale <poEditorCode> value), not necessarily the full app locale (e.g., fi_FI). Consider changing locale/terms/missing/{locale}/ to locale/terms/missing/{poEditorCode}/ for accuracy and consistency with the scripts.

Suggested change
This queries POEditor with `filters=untranslated` for each locale and writes fresh empty batch files to `locale/terms/missing/{locale}/`.
This queries POEditor with `filters=untranslated` for each locale and writes fresh empty batch files to `locale/terms/missing/{poEditorCode}/`.

Copilot uses AI. Check for mistakes.

### Step 2 — Preview what needs translation

Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/locale-poeditor-download.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,22 +224,22 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Generate missing terms for all locales
- name: Download missing terms for all locales from POEditor
if: inputs.operation_mode != 'audit-only'
run: |
echo "📋 Generating missing translation terms for all locales..."
npm run locale:missing
echo "✅ Missing terms files generated"
echo "📋 Downloading missing translation terms for all locales from POEditor..."
npm run locale:download:missing
echo "✅ Missing terms files downloaded"

- name: Commit missing terms for POEditor
if: inputs.operation_mode != 'audit-only'
run: |
if [ -d "locale/missing-terms" ] && [ -n "$(find locale/missing-terms -name 'poeditor-*.json' -type f 2>/dev/null)" ]; then
if [ -d "locale/terms/missing" ] && [ -n "$(find locale/terms/missing -name '*.json' -type f 2>/dev/null)" ]; then
echo "📝 Committing missing terms files..."
git add locale/missing-terms/poeditor-*.json
git add locale/terms/missing/
# Check if there are staged changes to commit
if ! git diff --cached --quiet; then
git commit -m "📊 Missing translation terms: Updated for all locales from master list"
git commit -m "locale: update missing translation terms from POEditor"
echo "✅ Missing terms files committed"
else
echo "ℹ️ No new missing terms to commit"
Expand Down Expand Up @@ -278,11 +278,11 @@ jobs:
**What's included:**
- Updated translation files from POEditor
- Generated locale JSON files
- 📊 Missing terms for all locales (in `locale/missing-terms/poeditor-*.json`)
- 📊 Missing terms for all locales (in `locale/terms/missing/`)
- Locale audit results

**Missing Terms Reports:**
For each incomplete locale, a `poeditor-{locale}.json` file contains all missing/untranslated terms from the master English list. These can be imported into POEditor to help translators complete the translations.
For each incomplete locale, batch files under `locale/terms/missing/{locale}/` contain all untranslated terms downloaded directly from POEditor. These can be used with `/locale-translate` or uploaded directly to POEditor.

Comment on lines 284 to 286
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The missing-terms output folder is keyed by POEditor language code (see locale/terms/missing/{poEditorCode}/ in the downloader and other docs). This PR body text uses {locale}, which can be different (e.g., pt_BR vs pt-br). Update the placeholder to {poEditorCode} to avoid confusion.

Copilot uses AI. Check for mistakes.
This PR was automatically created by the POEditor workflow.

Expand Down
33 changes: 14 additions & 19 deletions locale/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ locale/
### Locale Management
- `npm run locale:audit` - Generate locale completeness report
- `npm run locale:download` - Download latest translations from POEditor
- `npm run locale:download:missing` - Download **only untranslated (missing) terms** per locale from POEditor
- `npm run locale:term-extract` - Extract all translatable terms for POEditor upload

### Manual Scripts (require parameters)
Expand Down Expand Up @@ -63,33 +64,27 @@ ChurchCRM uses [POEditor](https://poeditor.com) as the primary translation manag

### Missing Terms Workflow

For identifying and prioritizing untranslated terms:
Uses POEditor's `filters=untranslated` export filter to download only the missing terms
directly from the API — no prior `locale:download` needed.

1. **Generate Missing Terms**: `npm run locale:missing`
- Compares POEditor terms against each locale's translated terms
- Creates JSON files in `locale/terms/missing/{locale}/`
- Files are batched (default 150 terms per file) for easy POEditor import

2. **Upload to POEditor**:
- Go to POEditor → Your Project → Import
- Select language and upload the JSON files from `locale/terms/missing/{locale}/`
- POEditor will highlight these as needing translation
```bash
npm run locale:download:missing # All locales
npm run locale:download:missing -- --locale fr # French only
```

3. **Translation Priority**:
- Files are named `{locale}-1.json`, `{locale}-2.json`, etc.
- Lower numbers = higher priority (most common terms)
- Translators should complete batch 1 before moving to batch 2
Output: `locale/terms/missing/{poEditorCode}/{code}-N.json`

4. **Download Updates**: After translators complete work, run `npm run locale:download`
Batch files contain at most 150 terms each. Locales with fewer than 10 missing terms are
skipped automatically. Files are ready for `/locale-translate` or direct upload to POEditor.

### Quick Reference Commands

```bash
# Full translation workflow
npm run locale:build # Extract all terms from source code
npm run locale:download # Download translations from POEditor
npm run locale:audit # Generate completeness report
npm run locale:missing # Generate missing term files for each locale
npm run locale:build # Extract all terms from source code
npm run locale:download # Download translations from POEditor
npm run locale:audit # Generate completeness report
npm run locale:download:missing # Fetch untranslated terms from POEditor
```

## 📝 Gettext System
Expand Down
245 changes: 0 additions & 245 deletions locale/scripts/locale-build-missing.js

This file was deleted.

2 changes: 1 addition & 1 deletion locale/scripts/locale-translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function countUntranslated(terms) {
function cmdList(localeMap) {
const missingDir = config.terms.missing;
if (!fs.existsSync(missingDir)) {
console.log('No missing terms directory found. Run: npm run locale:missing');
console.log('No missing terms directory found. Run: npm run locale:download:missing');
return;
}

Expand Down
Loading
Loading