Skip to content

Remove locale:missing; standardise on locale:download:missing#8204

Merged
DawoudIO merged 6 commits intomasterfrom
copilot/check-poeditor-api-missing-terms
Mar 6, 2026
Merged

Remove locale:missing; standardise on locale:download:missing#8204
DawoudIO merged 6 commits intomasterfrom
copilot/check-poeditor-api-missing-terms

Conversation

Copy link
Contributor

Copilot AI commented Mar 6, 2026

The local-diff approach (locale-build-missing.js / locale:missing) was redundant — POEditor's own filters=untranslated export API already computes missing terms server-side with no prior full download required. This removes the old script and wires everything to locale:download:missing.

Changes

  • Deleted locale/scripts/locale-build-missing.js
  • package.json — removed locale:missing script
  • locale/scripts/locale-translate.js — updated fallback hint to locale:download:missing
  • locale/scripts/poeditor-missing-downloader.js — cleaned up JSDoc (dropped cross-references to deleted file)
  • locale/README.md — collapsed two-option workflow to single canonical approach; removed locale:missing from scripts table and quick-reference block
  • .github/workflows/locale-poeditor-download.yml — replaced npm run locale:missing step with npm run locale:download:missing; updated commit step paths from locale/missing-terms/poeditor-*.jsonlocale/terms/missing/
  • .agents/skills/churchcrm/locale-ai-translation.md and .claude/commands/locale-release.md — Quick Start and scripts table updated to locale:download:missing

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…d:missing)

Uses POEditor filters=untranslated to download only untranslated terms per
locale directly from the API, without needing a full locale:download first.

- New: locale/scripts/poeditor-missing-downloader.js
- New npm script: locale:download:missing
- Updated: locale/README.md (documents both methods)
- Updated: .agents/skills/churchcrm/locale-ai-translation.md skill docs

Co-authored-by: DawoudIO <554959+DawoudIO@users.noreply.github.com>
Copilot AI changed the title [WIP] Investigate POEditor APIs for downloading missing terms feat: download missing terms per locale directly from POEditor API Mar 6, 2026
- Delete locale/scripts/locale-build-missing.js
- Remove locale:missing npm script from package.json
- Update locale-translate.js error hint to locale:download:missing
- Update poeditor-missing-downloader.js JSDoc (remove ref to deleted file)
- Update locale/README.md, locale-ai-translation.md skill, locale-release.md

Co-authored-by: DawoudIO <554959+DawoudIO@users.noreply.github.com>
Copilot AI changed the title feat: download missing terms per locale directly from POEditor API Replace locale:missing with POEditor API-based missing terms download Mar 6, 2026
- Replace npm run locale:missing with npm run locale:download:missing
- Update commit step path from locale/missing-terms/ to locale/terms/missing/
- Update PR body references to new path

Co-authored-by: DawoudIO <554959+DawoudIO@users.noreply.github.com>
Copilot AI changed the title Replace locale:missing with POEditor API-based missing terms download Remove locale:missing; standardise on locale:download:missing Mar 6, 2026
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@DawoudIO DawoudIO marked this pull request as ready for review March 6, 2026 16:07
@DawoudIO DawoudIO requested a review from a team as a code owner March 6, 2026 16:07
@DawoudIO DawoudIO requested review from DAcodedBEAT, DawoudIO, MrClever, bigtigerku, Copilot, grayeul and respencer and removed request for a team March 6, 2026 16:08
@DawoudIO DawoudIO merged commit 6463cca into master Mar 6, 2026
6 checks passed
@DawoudIO DawoudIO deleted the copilot/check-poeditor-api-missing-terms branch March 6, 2026 16:08
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR removes the redundant local diff–based missing-terms generator (locale:missing) and standardizes the workflow on downloading untranslated terms directly from POEditor via locale:download:missing.

Changes:

  • Replace locale:missing with locale:download:missing in npm scripts and related docs.
  • Add/update the POEditor missing-terms downloader workflow and commit paths to use locale/terms/missing/.
  • Remove the old locale-build-missing.js script and update references/messages accordingly.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
package.json Removes locale:missing and adds locale:download:missing script.
locale/scripts/poeditor-missing-downloader.js Implements missing-terms download from POEditor and writes batched JSON under locale/terms/missing/.
locale/scripts/locale-translate.js Updates the user hint to reference locale:download:missing.
locale/scripts/locale-build-missing.js Deletes the old local diff–based missing-terms generator.
locale/README.md Collapses missing-terms workflow to the single canonical POEditor-download approach.
.github/workflows/locale-poeditor-download.yml Switches the workflow step to locale:download:missing and commits from locale/terms/missing/.
.claude/commands/locale-release.md Updates release workflow docs to use locale:download:missing.
.agents/skills/churchcrm/locale-ai-translation.md Updates AI translation skill quick start and scripts table to use locale:download:missing.

Comment on lines +97 to +149
/**
* Fetch the untranslated terms for a locale from POEditor as a JSON object.
* Returns null when the locale has no untranslated terms (empty export).
*/
async function fetchUntranslatedTerms(poEditorLocale) {
const postData = new URLSearchParams({
api_token: apiToken,
id: PROJECT_ID,
language: poEditorLocale,
type: 'key_value_json',
filters: 'untranslated', // POEditor filter: only export terms without a translation
}).toString();

const response = await makeRequest(POEDITOR_API, postData);
const result = JSON.parse(response.data);

if (result.response.status !== 'success') {
throw new Error(result.response.message || 'Unknown POEditor error');
}

const downloadUrl = result.result.url;

// Download the JSON file from the signed S3 URL
return new Promise((resolve, reject) => {
https
.get(downloadUrl, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
let body = '';
res.on('data', (chunk) => {
body += chunk;
});
res.on('end', () =>
reject(
new Error(
`Download failed HTTP ${res.statusCode}: ${body.substring(0, 200)}`,
),
),
);
return;
}

let raw = '';
res.on('data', (chunk) => {
raw += chunk;
});
res.on('end', () => {
try {
const parsed = JSON.parse(raw);
resolve(parsed);
} catch (e) {
reject(new Error(`Failed to parse POEditor response: ${e.message}`));
}
});
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.

fetchUntranslatedTerms() claims it returns null for an empty export, but the implementation always JSON.parse(raw) and will throw if the download body is empty/whitespace. Consider treating an empty download as “no missing terms” (e.g., return {}) and align the JSDoc + callers accordingly, so fully-translated locales don’t get counted as failures.

Copilot uses AI. Check for mistakes.
Comment on lines +178 to +186
const entries = Object.entries(missingTerms);
const files = [];
let batchNumber = 1;

for (let i = 0; i < entries.length; i += TERMS_PER_FILE) {
const batch = Object.fromEntries(entries.slice(i, i + TERMS_PER_FILE));
const filename = path.join(localeOutDir, `${poEditorCode}-${batchNumber}.json`);
fs.writeFileSync(filename, JSON.stringify(batch, null, 2) + '\n');
files.push({ number: batchNumber, filename, count: Object.keys(batch).length });
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.

Batch file contents are built from Object.entries(missingTerms) without any deterministic ordering. If POEditor changes export ordering, batching can churn and create noisy diffs/commits. Sort the entries (e.g., by key) before slicing into batches to keep output stable across runs.

Copilot uses AI. Check for mistakes.
Comment on lines 284 to 286
**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.

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 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.
Comment on lines 19 to 23
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
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.
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.

3 participants