dotnet / project-system

The .NET Project System for Visual Studio
MIT License
968 stars 386 forks source link

Property page .xaml rule files do not support static resources for localization #7522

Open japarson opened 3 years ago

japarson commented 3 years ago

Visual Studio Version: Microsoft Visual Studio Enterprise 2022 d17.0 (64-bit) Version 17.0.0 Preview 3.1 [31616.260.d17.0]

Summary: When authoring a property page .xaml rules file, we are not able to reference static resources to be used for property fields such as Display Name or Description.

Steps to Reproduce:

  1. Create a property page .xaml rule file by following this documentation.

  2. Create a Resources.resx file and add a string to the file, e.g. Test -> test.

  3. Add the xaml namespace that corresponds to the resources file in your rule file. image

  4. Add a property to the rule file with a display name that references the resources file using the static handler. image

Expected Behavior: The page is loaded and the property displays the value from the resources file.

Actual Behavior: The page does not get loaded in the Properties editor.

User Impact: We are not able to use our existing resource files to localize the new property pages. The only alternative is to use xliff-tasks which looks complicated to set up in a repository which already has an existing localization system. Furthermore, it would be wasteful to go through the process of setting up xliff-tasks only to switch back to using resource files once they are supported.

japarson commented 3 years ago

@tmeschter @drewnoakes

tmeschter commented 3 years ago

I believe we will need to update CPS to handle this. When loading XAML, CPS instantiates a XamlSchemaContext with a very limited set of reference assemblies. Later, when x:Static tries to find the assembly that corresponds to the properties XML namespace (in the original example) it is unable to do so as it is not in the set.

I see a few possible options:

  1. Add an extension point in the form of a MEF component that allows additional assemblies to be added to the XamlSchemaContext up front
  2. Pass a modified XamlSchemaContext that handles assembly resolve events (it's not clear if this would actually work, though)
  3. Pre-process the XAML files to find references to additional assemblies, load them, and add them to the XamlSchemaContext

The second option would be ideal from a usability point of view. However, I suspect the set of reference assemblies is limited to prevent the deserialization of arbitrary types and the associated security risks. That points to the first option as the better one--if you've already got a MEF component loading in VS the serialization concern is moot.

tmeschter commented 3 years ago

Note that this would be an incredibly useful feature. In our own repo it would allow us to ship just one copy of each .xaml file (instead of 13 or so) and would allow localization of any part of the .xaml file, not just the parts understood by xliff-tasks.

drewnoakes commented 3 years ago

In our own repo it would allow us to ship just one copy of each .xaml file (instead of 13 or so) and would allow localization of any part of the .xaml file, not just the parts understood by xliff-tasks.

I'd be interested in knowing how that might work.

tmeschter commented 3 years ago

@drewnoakes xliff-tasks has hard-coded knowledge of which XML elements and attributes in the XAML file need to be localized, and only those can be localized. My understanding is that the x:Static syntax can be used just about anywhere.

Rather than picking a different .xaml file based on the VS locale settings, we would always load the same file but use x:Static to read localized data stored in resources.

drewnoakes commented 3 years ago

I see, yes that could work. It'd make those source XAML files a bit harder to work with, so we'd need to assess the tradeoffs of both approaches.

tmeschter commented 3 years ago

Indeed. I think the high-order bit is that we have options because we designed this system, we've already adopted xliff-tasks, and we know who to talk to if we need changes there, but for everyone else translating things this way is much more difficult. If we can reduce the problem to translating resources in .resx files that will be a win for many teams.

danegsta commented 2 years ago

This particular issue is preventing the VS Containers Tools team from localizing our launch profile UI for the Containers (Docker) extension in VS 2022. We don't have an SDK component, so we don't ship external xaml rules for our UI and our localization pipeline doesn't support generating language specific resource names for the embedded xaml rules either.

Supporting localized resources via x:Static as proposed above would unblock us and fit nicely with our existing localization workflow.

drewnoakes commented 2 years ago

@danegsta have you investigated specifying your rules in code? If you do that, you're able to use strings from resource dictionaries.

danegsta commented 2 years ago

We're specifying our rules in code, but we've been tracking this particular issue to see when we could start implementing localized strings via resources, but it sounds like the work has already been done to enable that scenario?

danegsta commented 2 years ago

Oh, I see you mean that there's a new IRuleObjectProvider type we can implement vs. an embedded .xaml file. That seems like it would hopefully work to get us unblocked.

drewnoakes commented 2 years ago

That's right. You can remove XAML altogether. The approach is documented here. Let us know if the docs have any gaps and we'll improve them. Feel free to send a PR too.

You can still use the property specification documentation. You just have to map the XAML examples to code, which is straightforward.