docs
docs copied to clipboard
SatelliteResourceLanguages clarifications for listing multiple languages
I'd like to request two clarifications to the documentation of the SatelliteResourceLanguages property:
- Change the example to show how to list more than one language, specifically that semicolons must be used as separators. https://github.com/dotnet/docs/blob/ff7e3568e4bfb7283be4bbdb65c2b0024e8169bb/docs/core/project-sdk/msbuild-props.md?plain=1#L386-L390
- Extend the note to explicitly recommend against using the MSBuild command-line option
-property:name=valueto set this property, because it is not possible to list more than one language that way. https://github.com/dotnet/docs/blob/ff7e3568e4bfb7283be4bbdb65c2b0024e8169bb/docs/core/project-sdk/msbuild-props.md?plain=1#L392-L393
Context
I tried to set SatelliteResourceLanguages on the dotnet publish command line, using .NET SDK 6.0.302 on Windows:
PS> dotnet publish -o "$(Get-Location)/bin/net6.0" --no-self-contained --configuration Release --framework net6.0 -p:SatelliteResourceLanguages="en;de"
Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
MSBUILD : error MSB1006: Property is not valid.
Switch: de
For switch syntax, type "MSBuild -help"
It didn't work, because the -p option parsed the semicolon as terminating the property value and starting another property name, regardless of the quotation marks.
Next, I tried encoding the semicolon as %3B, as listed in MSBuild special characters:
PS> dotnet publish -o "$(Get-Location)/bin/net6.0" --no-self-contained --configuration Release --framework net6.0 -p:SatelliteResourceLanguages="en%3Ade"
Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
Restored C:\MyApp\src\MyApp\MyApp.csproj (in 542 ms).
MyApp -> C:\MyApp\src\MyApp\bin\Release\net6.0\MyApp.dll
MyApp -> C:\MyApp\bin\net6.0\
That appeared to succeed, but .NET SDK did not copy the "de" satellite assembly to C:\MyApp\bin\net6.0\de\System.CommandLine.resources.dll. I think the reason is that the SatelliteResourceLanguages parameter of the ResolvePackageAssets task is defined as ITaskItem[] rather than string, so when the ResolvePackageAssets target passes $(SatelliteResourceLanguages) to that parameter, MSBuild has to split the string value to items, but if the semicolon was encoded, then MSBuild doesn't treat it as a list separator.
Finally, I set the property in Directory.Build.props, to make it apply to all projects in the solution
<Project>
<PropertyGroup>
<SatelliteResourceLanguages>en;de</SatelliteResourceLanguages>
</PropertyGroup>
</Project>
and ran dotnet publish without the -property:SatelliteResourceLanguages=value option, and that worked fine.
Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
- ID: cb4428fc-215c-78e1-5ff0-fe73f7a08260
- Version Independent ID: 6741b1de-38a4-fbb1-d79d-acc47d549a2d
- Content: MSBuild properties for Microsoft.NET.Sdk - .NET
- Content Source: docs/core/project-sdk/msbuild-props.md
- Product: dotnet-fundamentals
- GitHub Login: @gewarren
- Microsoft Alias: gewarren
2. Extend the note to explicitly recommend against using the MSBuild command-line option
-property:name=valueto set this property, because it is not possible to list more than one language that way.
This might have changed recently; see https://github.com/dotnet/sdk/issues/27059. However, that was reported as a bug.
Thanks @KalleOlaviNiemitalo. I'm not going to add the note about no. 2) since it was confirmed yesterday that this is a bug.
Well, it seems possible to list multiple languages in -p:SatelliteResourceLanguages= after all, but it requires some gymnastics.
The following project demonstrates how MSBuild converts the value of a property to items. I believe MSBuild uses the same kind of conversion when the .NET SDK passes $(SatelliteResourceLanguages) to the ResolvePackageAssets task:
<Project>
<ItemGroup>
<Item Include="$(Prop)" />
</ItemGroup>
<Target Name="Build">
<Message Importance="high" Text="Property: [$(Prop)]" />
<Message Importance="high" Text="Items: @(Item->'[%(Identity)]')" />
</Target>
</Project>
Using cmd.exe on Windows to run "Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET" via .NET SDK 6.0.303, which does not have the bug https://github.com/dotnet/sdk/issues/27059:
- The property value cannot contain a plain semicolon because that gets treated as a separator between name=value pairs.
dotnet msbuild multi.msbuildproj -nologo -p:Prop=de;en MSBUILD : error MSB1006: Property is not valid. Switch: en For switch syntax, type "MSBuild -help" - A semicolon encoded as
%3Bis accepted, but the conversion to items does not treat it as a delimiter.dotnet msbuild multi.msbuildproj -nologo -p:Prop=de%3Ben Property: [de;en] Items: [de;en] - A pair of quotation marks around the property value makes no difference.
dotnet msbuild multi.msbuildproj -nologo -p:Prop="de;en" MSBUILD : error MSB1006: Property is not valid. Switch: en For switch syntax, type "MSBuild -help" - Two pairs don't work either.
dotnet msbuild multi.msbuildproj -nologo -p:Prop=""de;en"" MSBUILD : error MSB1006: Property is not valid. Switch: en For switch syntax, type "MSBuild -help" - Three pairs of quotation marks make it work; the semicolon is parsed as a item separator, but not as a name=value separator.
dotnet msbuild multi.msbuildproj -nologo -p:Prop="""de;en""" Property: [de;en] Items: [de];[en]
So yeah, I was wrong and it's possible to specify multiple languages using -p. However, the triply double-quoted syntax is rather unobvious and shell-dependent (PowerShell on Windows seems to require --% for it). If you have a docs page for how to correctly quote MSBuild command-line options, then it would be good to link to that from there.
This works in PowerShell 7.2.5 on Windows
dotnet msbuild multi.msbuildproj -nologo '-p:Prop="""de;en"""'
This works in bash shipped with Git for Windows 2.36.0
dotnet msbuild multi.msbuildproj -nologo -p:Prop='"de;en"'
Reopening to document the triple quote syntax that's required to specify multiple languages on the command line.