Skip to content

Fix ResXFileRef/Bitmap href paths in translated .resx/.vsct: relative instead of absolute#17071

Draft
mwiemer-microsoft with Copilot wants to merge 3 commits into
mainfrom
copilot/translate-resx-file-refs
Draft

Fix ResXFileRef/Bitmap href paths in translated .resx/.vsct: relative instead of absolute#17071
mwiemer-microsoft with Copilot wants to merge 3 commits into
mainfrom
copilot/translate-resx-file-refs

Conversation

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

TranslateSource was baking absolute paths into translated .resx and .vsct files written to the intermediate output directory. Any repo rename/move caused subsequent builds to fail with MSB3103: Could not find a part of the path 'C:\old-location\...' because the stale absolute paths no longer resolved.

Root cause

RewriteRelativePathsToAbsolute in ResxDocument and VsctDocument resolved ResXFileRef/Bitmap href paths against the source .resx/.vsct directory and stored them as absolute paths — making the cached output location-dependent.

Changes

  • TranslatableDocument — replaces the old single-arg RewriteRelativePathsToAbsolute(sourceFullPath) with:

    • RewriteRelativePathsForOutputPath(sourceFullPath, outputFullPath) — new virtual method subclasses override
    • MakeRelativePath(fromDirectory, toPath) — protected static helper using Uri.MakeRelativeUri; falls back to absolute when source/output are on different drives
  • ResxDocument — overrides RewriteRelativePathsForOutputPath; rewrites ResXFileRef value paths relative to the output .resx directory

  • VsctDocument — same fix for <Bitmap href="..."> attributes

  • TranslateSource — calls RewriteRelativePathsForOutputPath(sourcePath, translatedFullPath) instead of the old single-arg form

  • Tests — updated ResxDocumentTests and VsctDocumentTests to assert the output contains a relative path and does not contain the absolute base path; covers the typical case where source and output directories differ

Before / after (intermediate MyProject.resx):

<!-- Before: breaks after repo rename -->
<value>C:\Users\me\repos\myproject\src\MyProject\Dictionary.dic;System.String</value>

<!-- After: survives repo rename/move -->
<value>..\..\..\src\MyProject\Dictionary.dic;System.String</value>

To double check:

… of absolute

When TranslateSource writes the translated .resx (and .vsct) to the
intermediate output directory, ResXFileRef/Bitmap href entries previously
had their paths rewritten to absolute paths. This broke incremental builds
after the repo was renamed or moved, because the baked-in absolute path
no longer existed.

Fix: compute the path relative to the translated output file's directory
instead of an absolute path. Uses Uri.MakeRelativeUri for cross-platform
compatibility. Falls back to absolute path if source/output are on
different drives (Windows).

- Add RewriteRelativePathsForOutputPath(sourceFullPath, outputFullPath) to
  TranslatableDocument base class with MakeRelativePath helper
- Override in ResxDocument (ResXFileRef data entries) and VsctDocument
  (Bitmap href attributes) to use relative paths
- Update TranslateSource to call the new method with both source and
  translated output paths
- Update tests to verify relative-path behavior
Copilot AI requested review from Copilot and removed request for Copilot July 2, 2026 18:42
Copilot AI requested review from Copilot and removed request for Copilot July 2, 2026 18:45
Copilot AI changed the title [WIP] Fix ResXFileRef absolute path issue in translated .resx files Fix ResXFileRef/Bitmap href paths in translated .resx/.vsct: relative instead of absolute Jul 2, 2026
Copilot AI requested a review from mwiemer-microsoft July 2, 2026 18:46
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.

TranslateSource bakes absolute ResXFileRef paths into cached translated .resx files, breaking incremental builds after repo rename/move (MSB3103)

2 participants