Skip to content

Fix three cases where the converter silently drops entries - #60

Merged
Zintixx merged 3 commits into
mainfrom
fix/converter-silently-drops-entries
Jul 28, 2026
Merged

Fix three cases where the converter silently drops entries#60
Zintixx merged 3 commits into
mainfrom
fix/converter-silently-drops-entries

Conversation

@AngeloTadeucci

@AngeloTadeucci AngeloTadeucci commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Three separate bugs in WeblateConverter cause json-to-xml-all to lose data without failing. Because nothing errors, the loss only surfaces later as missing strings in-game.

Found while adopting the #55 JSON-source model on a fork, where the regenerated output was diffed against the pre-#55 tree.

1. Split quest files deleted with no replacement

RemoveAbsorbedSourceFiles deleted every questdescription_* / scriptquest_* file for a locale before checking whether the combined output that absorbs them would actually be written. A partially translated locale has no questdescription_final.json or scriptquest.json, so the files were deleted and nothing was put back.

pt is the clear case: it only has itemname.json and korflash.json, and lost 29 files holding roughly 20.9k translated attributes. Removal is now gated on the corresponding combined JSON being present.

2. Trailing space in a filename misses every lookup

questdescription_famefield .xml ships with a trailing space in its name. That misses the key-attribute lookup, falls back to the default id, finds no such attribute (the elements use questID), and drops all 106 entries. Fixed by trimming the lookup key, which also guards against any other stray whitespace.

3. Two files absent from the lookup tables

questdescription_daily and questdescription_eventjp were in neither the element-name nor the key-attribute table, which is the same failure mode as 2. Added to both, matching the other 19 questdescription_* entries.

Evidence

Xml/string/de is the only locale that still has the famefield file, and de has no JSON so it was never regenerated. Running xml-to-json de:

famefield parse warnings famefield questIDs reaching questdescription_final.json
before 108 0
after 2 106

Scope

This stops further loss but does not recover what is already gone. As of #55 the tree has no pt quest/script files, no questdescription_daily, and only the de copy of famefield. That content is still in the history before #55 if you want it restored, which I am happy to do as a follow-up.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Bug Fixes
    • Prevented removal of locale-specific split fragment files when the corresponding combined output files weren’t successfully generated, preserving partially converted content.
    • Improved JSON-to-XML filename parsing by trimming trailing whitespace from derived lookup keys.
    • Added/updated conversion mappings so daily, daily mission, and event quest descriptions map correctly to the expected XML element and questID key attribute.

Each of these makes json-to-xml-all lose data without failing, so the loss only
shows up as missing strings in-game.

1. RemoveAbsorbedSourceFiles deleted the individual questdescription_* and
   scriptquest_* files before checking whether the combined output that replaces
   them would actually be written for that locale. A partially translated locale
   has no questdescription_final.json or scriptquest.json, so the split files were
   deleted and nothing was put back. On pt this removed 29 files holding roughly
   20.9k translated attributes. The removal is now gated on the corresponding
   combined JSON being present.

2. "questdescription_famefield .xml" ships with a trailing space in its filename.
   That misses the key-attribute lookup, so it falls back to the default "id",
   finds no such attribute (the elements use questID), and every entry in the file
   is dropped. Fixed by trimming the lookup key.

3. questdescription_daily and questdescription_eventjp were missing from both
   lookup tables, which is the same failure mode as 2.

Checked against Xml/string/de, the one locale that still has the famefield file:
xml-to-json de reports 108 parse warnings for it before this change and 2 after,
and all 106 of its questIDs now reach questdescription_final.json.

Note that the data these bugs dropped is already gone from the tree as of #55
(pt has no quest/script files left, questdescription_daily is gone, and only the
de copy of famefield survives). This change stops further loss but does not
recover that content, which is still available in the history before #55.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Zintixx, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6879533e-caa2-4432-ac43-f542e5f063cb

📥 Commits

Reviewing files that changed from the base of the PR and between b71ad28 and 9c2a4d8.

📒 Files selected for processing (1)
  • WeblateConverter/Converter/Converter.cs
📝 Walkthrough

Walkthrough

Converter.cs makes absorbed-file cleanup depend on combined outputs written during the current conversion run, tracks those outputs during JSON-to-XML processing, trims filename lookup keys, and adds quest description mappings.

Changes

Converter updates

Layer / File(s) Summary
Locale-aware absorbed-file cleanup
WeblateConverter/Converter/Converter.cs
Conversion tracks whether combined quest and script outputs were written, then removes matching fragments without deleting the combined outputs themselves.
Filename lookup normalization and mappings
WeblateConverter/Converter/Converter.cs
Filename-derived lookup keys are trimmed, and daily, daily mission, and event JP quest description variants map to the appropriate XML element and key attribute.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: zintixx

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: it describes fixing three converter bugs that caused silent entry loss.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/converter-silently-drops-entries

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@WeblateConverter/Converter/Converter.cs`:
- Around line 588-599: Update the cleanup flow in ProcessJsonToXml to track
whether questdescription_final.json or scriptquest.json was successfully written
with valid combined output, rather than only checking filename presence. Defer
deletion of source fragments until after the corresponding conversion/write
succeeds, and preserve the existing behavior of skipping empty or malformed JSON
without deleting its source data.
- Around line 621-624: Update IsAbsorbedByCombinedOutput so
questdescription_final.xml is explicitly excluded from the questdescription_
prefix match, while preserving absorption behavior for other source fragments
and the existing hasQuestOutput result.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a2fd25f2-978f-4927-9edf-6d7af72a8a6b

📥 Commits

Reviewing files that changed from the base of the PR and between 83a616e and 93b05f7.

📒 Files selected for processing (1)
  • WeblateConverter/Converter/Converter.cs

Comment thread WeblateConverter/Converter/Converter.cs Outdated
Comment thread WeblateConverter/Converter/Converter.cs Outdated
…output is written

Addresses CodeRabbit's two findings on the absorbed-file cleanup:

1. RemoveAbsorbedSourceFiles ran BEFORE generation and gated on the combined JSON
   merely existing, so an empty questdescription_final.json/scriptquest.json (skipped)
   or a failed conversion still deleted the fragments with nothing written back. Cleanup
   now runs AFTER the loop and deletes a family's fragments only if its combined output
   was actually written this run.

2. questdescription_final.xml matches the questdescription_ prefix, so the cleanup would
   delete the combined output itself. IsAbsorbedByCombinedOutput now excludes both
   combined outputs explicitly.

Verified end-to-end: empty combined -> fragments preserved; non-empty combined ->
fragments removed and the combined output survives; json-to-xml-all + verify-all clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Zintixx

Zintixx commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@WeblateConverter/Converter/Converter.cs`:
- Around line 671-677: Update ConvertQuestDescriptionFinalWithSorting to return
false when questEntries.Count is zero before saving, and return true only after
successfully saving a non-empty output. In the jsonFile handling block, assign
questFinalWritten from that helper result instead of marking it unconditionally;
keep scriptFinalWritten behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bdc741c5-2cd2-44b7-aada-f6812be21471

📥 Commits

Reviewing files that changed from the base of the PR and between 93b05f7 and b71ad28.

📒 Files selected for processing (1)
  • WeblateConverter/Converter/Converter.cs

Comment thread WeblateConverter/Converter/Converter.cs Outdated
Follow-up to CodeRabbit: a non-empty questdescription_final.json whose quest IDs
are all unparseable produced an empty questEntries list, which (a) overwrote the
existing questdescription_final.xml with an empty file and (b) still marked the
output written, so the absorbed source fragments were deleted.

ConvertQuestDescriptionFinalWithSorting now returns bool: on an empty result it
skips the save (leaving the existing combined intact) and returns false; the caller
assigns questFinalWritten from that, so cleanup runs only after a real, non-empty write.

Verified: all-invalid-id JSON leaves both the combined output and its fragments
untouched; json-to-xml-all + verify-all remain clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Zintixx
Zintixx merged commit 6ff7abf into main Jul 28, 2026
4 checks passed
Zintixx added a commit that referenced this pull request Jul 28, 2026
The in-place flip's RemoveAbsorbedSourceFiles deleted pt's questdescription_*/
scriptquest_* fragments even though pt has no combined questdescription_final.json/
scriptquest.json to replace them (the bug fixed in #60), so the data was lost.

Restores the 29 files from 3b7ec8a (last commit before #55): ~5,864 quest entries,
of which 4,755 are real Portuguese translations. Verified: they parse as valid XML,
and with the #60 fix in place a full json-to-xml-all no longer deletes them
(pt has no combined output). verify-all passes.

Other locales (en/cn/jp/kr) are not affected — their fragments were correctly
absorbed into the committed combined outputs, so their data is preserved.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Zintixx added a commit that referenced this pull request Jul 29, 2026
The original XML->JSON dropped questdescription_famefield's 106 entries
because of the trailing-space filename bug (fixed in #60), so they never
made it into the combined questdescription_final.json.

- en/cn/jp: add the 106 missing famefield entries (real translations, e.g.
  'Cry of the Wildflower', 'The Case of the Missing Plungers').
- ko: the base-language template held Chinese for all 106 famefield keys
  (the missing-keys merge backfilled ko from cn when ko's own parse failed).
  Correct them to the real Korean from the KMS2 source (e.g. 野花的悲鸣 -> 야생화의 비명).

No original key dropped, no non-famefield key changed. Verified end-to-end:
json-to-xml regenerates valid XML for the recovered entries and 'verify' passes.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants