-
-
Notifications
You must be signed in to change notification settings - Fork 555
Fix plural forms structure in POEditor scripts #9342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -139,11 +139,39 @@ async function fetchUntranslatedTerms(poEditorLocale) { | |
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Restructure POEditor export from malformed to correct format for upload. | ||
| * POEditor returns: { "one": { term1: "...", term2: "..." }, "other": { ... } } | ||
| * We need: { "term1": { "one": "...", "other": "..." }, "term2": { ... } } | ||
| */ | ||
| function restructurePluralForms(data) { | ||
| if (!data.one && !data.other) return data; | ||
| if (typeof data.one === 'object' && typeof data.other === 'object') { | ||
| const restructured = {}; | ||
| for (const [key, value] of Object.entries(data)) { | ||
| if (key !== 'one' && key !== 'other' && typeof value === 'string') { | ||
| restructured[key] = value; | ||
| } | ||
| } | ||
| const termKeys = new Set([...Object.keys(data.one || {}), ...Object.keys(data.other || {})]); | ||
| for (const term of termKeys) { | ||
| const pluralForms = {}; | ||
| if (data.one != null && data.one[term] !== undefined && data.one[term] !== null) pluralForms.one = data.one[term]; | ||
| if (data.other != null && data.other[term] !== undefined && data.other[term] !== null) pluralForms.other = data.other[term]; | ||
| if (Object.keys(pluralForms).length > 0) restructured[term] = pluralForms; | ||
| } | ||
| return restructured; | ||
| } | ||
| return data; | ||
| } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
[HIGH] Truthy check silently drops all untranslated plural terms — still unaddressed if (data.one && data.one[term]) pluralForms.one = data.one[term]; // "" is falsy!
if (data.other && data.other[term]) pluralForms.other = data.other[term];
if (Object.keys(pluralForms).length > 0) restructured[term] = pluralForms;POEditor returns Fix: if (data.one != null && data.one[term] !== undefined && data.one[term] !== null)
pluralForms.one = data.one[term];
if (data.other != null && data.other[term] !== undefined && data.other[term] !== null)
pluralForms.other = data.other[term]; |
||
|
|
||
| /** | ||
| * Save missing terms in batched JSON files under MISSING_OUTPUT_DIR/{poEditorCode}/ | ||
| * Returns array of written file paths. | ||
| */ | ||
| function saveBatchedMissingTerms(poEditorCode, missingTerms) { | ||
| missingTerms = restructurePluralForms(missingTerms); | ||
|
|
||
| const localeOutDir = path.join(MISSING_OUTPUT_DIR, poEditorCode); | ||
|
|
||
| if (!fs.existsSync(localeOutDir)) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -188,6 +188,33 @@ function loadEnglishOkAllowlist() { | |
| } | ||
| } | ||
|
|
||
| // ── Plural form restructuring ─────────────────────────────────────────────── | ||
|
|
||
| /** | ||
| * Defensive restructure for malformed plural forms from POEditor export. | ||
| * If batch file has top-level "one"/"other", fixes to proper nesting. | ||
| */ | ||
| function restructurePluralForms(data) { | ||
| if (!data.one && !data.other) return data; | ||
| if (typeof data.one === 'object' && typeof data.other === 'object') { | ||
| const restructured = {}; | ||
| for (const [key, value] of Object.entries(data)) { | ||
| if (key !== 'one' && key !== 'other' && typeof value === 'string') { | ||
| restructured[key] = value; | ||
| } | ||
| } | ||
| const termKeys = new Set([...Object.keys(data.one || {}), ...Object.keys(data.other || {})]); | ||
| for (const term of termKeys) { | ||
| const pluralForms = {}; | ||
| if (data.one != null && data.one[term] !== undefined && data.one[term] !== null) pluralForms.one = data.one[term]; | ||
| if (data.other != null && data.other[term] !== undefined && data.other[term] !== null) pluralForms.other = data.other[term]; | ||
| if (Object.keys(pluralForms).length > 0) restructured[term] = pluralForms; | ||
| } | ||
| return restructured; | ||
| } | ||
| return data; | ||
| } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
[HIGH] Same truthy-check bug silently drops all plural terms during analysis Identical logic to the downloader: The fix is the same: replace truthiness checks with explicit
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
[HIGH] Same truthy-check bug — Identical logic to the downloader. After Apply the same null-guard fix as in the downloader. |
||
|
|
||
| // ── Term analysis ──────────────────────────────────────────────────────────── | ||
|
|
||
| /** | ||
|
|
@@ -229,7 +256,8 @@ function isNotIdenticalToKey(termKey, value) { | |
| * @param {Set<string>} [englishOkSet] - optional set of terms safe to upload as-is | ||
| */ | ||
| function analyzeFile(filePath, englishOkSet = new Set()) { | ||
| const raw = JSON.parse(fs.readFileSync(filePath, 'utf8')); | ||
| let raw = JSON.parse(fs.readFileSync(filePath, 'utf8')); | ||
| raw = restructurePluralForms(raw); // Defensive: fix malformed plural structure if present | ||
| const localizedTerms = {}; | ||
| const suspectTerms = {}; | ||
| const emptyTerms = {}; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[HIGH] Truthy check silently drops all untranslated plural terms
POEditor returns
""(empty string) for every untranslated term — exactly the case this function is meant to handle. Empty strings are falsy in JavaScript, sodata.one[term]always fails the guard,pluralFormsstays{}, and every term is silently discarded. The function returns{}for its primary input, causingsaveBatchedMissingTermsto write empty batch files for all plural-form locales.Fix: