Skip to content

fix(xcloc): sync project translations to xliffDoc before export#43

Merged
sirily11 merged 2 commits into
mainfrom
copilot/fix-exported-translation-files
Apr 17, 2026
Merged

fix(xcloc): sync project translations to xliffDoc before export#43
sirily11 merged 2 commits into
mainfrom
copilot/fix-exported-translation-files

Conversation

Copilot AI commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Exported XCLOC files were missing all translations despite the UI showing them as complete.

Root cause: The worker saves translated entries to projects.content but not to projects.formatData (which holds xliffDoc). The exportFile() method serialized xliffDoc directly—so it exported the stale, untranslated XLIFF.

Fix:

  • Added syncAllToXliff(doc) to XclocClient, which writes entry.targetText from this.project.resources into the corresponding XLIFF trans-units before serialization
  • exportFile() now always clones and syncs before serializing, matching the pattern already used by PoClient.syncAllToDocument()
// Before: serialized stale xliffDoc directly
let docToSerialize = this.xliffDoc;

// After: clone and sync translations from project content first
const docToSerialize = structuredClone(this.xliffDoc);
this.syncAllToXliff(docToSerialize);
  • Added a test reproducing the exact scenario: loadFromJson with translated content + stale xliffDoc, verifying the export includes translations

Copilot AI linked an issue Apr 17, 2026 that may be closed by this pull request
@vercel

vercel Bot commented Apr 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
universal-translation Ready Ready Preview, Comment Apr 17, 2026 11:20am

Request Review

The export was serializing xliffDoc directly without syncing translations
from the project content. When the worker saved content (with translations)
but did not save formatData (with xliffDoc), the exported file would be
missing all translations.

Add syncAllToXliff() method and call it in exportFile() before serializing,
mirroring the pattern used by PO client's syncAllToDocument().

Agent-Logs-Url: https://github.com/rxtech-lab/universal-translation/sessions/11861516-0b38-4803-8640-7f3555f7962c

Co-authored-by: sirily11 <32106111+sirily11@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix exported translation files missing translations fix(xcloc): sync project translations to xliffDoc before export Apr 17, 2026
Copilot AI requested a review from sirily11 April 17, 2026 11:21
@sirily11 sirily11 marked this pull request as ready for review April 17, 2026 11:26
Copilot AI review requested due to automatic review settings April 17, 2026 11:26
@sirily11 sirily11 enabled auto-merge (squash) April 17, 2026 11:28
@sirily11 sirily11 merged commit d36ba44 into main Apr 17, 2026
9 checks passed
@sirily11 sirily11 deleted the copilot/fix-exported-translation-files branch April 17, 2026 11:30

Copilot AI 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.

Pull request overview

Fixes XCLOC exports missing translations by ensuring xliffDoc is synced from the normalized project.resources content immediately before serialization.

Changes:

  • Clone xliffDoc in exportFile() and sync project entry translations into the cloned XLIFF document prior to serialization.
  • Add syncAllToXliff(doc) helper to apply project translations back into an XLIFF document.
  • Add a regression test covering loadFromJson(contentWithTranslations, staleFormatData) and verifying exported XLIFF contains the translations.

Reviewed changes

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

File Description
lib/translation/xcloc/client.ts Sync project translations into a cloned XLIFF doc before export to avoid serializing stale formatData.xliffDoc.
tests/translation/xcloc/client.test.ts Adds regression test reproducing stale xliffDoc export and asserting exported XLIFF includes translations.

const tu = xliffFile.transUnits.find((t) => t.id === entry.id);
if (!tu) continue;

tu.target = entry.targetText;

Copilot AI Apr 17, 2026

Copy link

Choose a reason for hiding this comment

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

syncAllToXliff() only syncs entry.targetText into tu.target, but does not sync entry.comment into tu.note. If formatData.xliffDoc is stale (the exact scenario this PR fixes), updated entry comments stored in projects.content will still be lost on export. Consider also copying entry.comment to the corresponding trans-unit note during the sync (clearing it when the project comment is empty/undefined).

Suggested change
tu.target = entry.targetText;
tu.target = entry.targetText;
tu.note = entry.comment ? entry.comment : undefined;

Copilot uses AI. Check for mistakes.
Comment on lines +556 to +557
tu.target = entry.targetText;
}

Copilot AI Apr 17, 2026

Copy link

Choose a reason for hiding this comment

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

syncAllToXliff() assigns tu.target = entry.targetText for every entry. Since the normalized model uses empty string to mean “not translated yet”, this will introduce empty <target></target> elements for all untranslated units when the original XLIFF omitted <target> entirely. To keep export semantics consistent (and avoid bloating the output), consider only setting tu.target when entry.targetText.trim() !== "", and otherwise leaving it undefined/removing it.

Copilot uses AI. Check for mistakes.
@sirily11

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.2.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exported translation files missing translations

3 participants