You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Xamarin.Android.Build.Tasks] Make XA4214 warning localizable
Context: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1009374/
This commit prepares one MSBuild message for localization, establishing
the general steps to follow for other messages. The general steps are:
1. Add the message to
`src/Xamarin.Android.Build.Tasks/Properties/Resources.resx`. Use
the message code as the name of the resource. For example, for the
message text associated with code `XA4214`, use `XA4214` as the
name.
Be sure to use Visual Studio or Visual Studio for Mac to edit the
`.resx` file so that the `ResXFileCodeGenerator` tool will run and
update the corresponding `Resources.Designer.cs` file.
2. In the call to `LogCodedError()` or `LogCodedWarning()`, reference
the message string using the generated C# property name like
`Properties.Resources.XA4214`.
3. After adding the new message, build
`Xamarin.Android.Build.Tasks.csproj` locally. This will run the
targets from [dotnet/xliff-tasks][0] to update the `.xlf` [XLIFF][1]
localization files with the latest changes from the `.resx` file.
4. Include the changes to the`.resx` file as well as the generated
changes to the `Resources.Designer.cs` file and the `.xlf` files in
the commit.
This first example also establishes a few guidelines for specific
scenarios:
* If a message code is used in multiple calls to `LogCodedError()` or
`LogCodedWarning()` that each logs a different message, append short
descriptive phrases to the end of the code to create additional
resource names as needed.
* To include values of variables in the message, use format items like
`{0}` and `{1}` rather than string interpolation or string
concatenation.
String interpolation won't work because string resources are not
subject to interpolation. String concatenation should also be
avoided because it means the message text will be split across
multiple string resources, which makes it more complicated to
provide appropriate context about the message for the translation
team.
* Use the comments field in the `.resx` file to provide additional
context to the translation team about the message. For example, for
a message that includes a format item like `{0}`, it can sometimes
be helpful to add a comment about what will appear for that item in
the final formatted string:
{0} - The managed type name
For a few more examples, see the dotnet/sdk repo:
https://github.com/dotnet/sdk/blob/master/src/Tasks/Common/Resources/Strings.resx
Implementation details
======================
The `.resx` file is named `Resources.resx` and located in the
`src/Xamarin.Android.Build.Tasks/Properties/` directory. This follows
what the nonpublic xamarin/designer and xamarin/XamarinVS repositories
do.
The `.resx` file is stored with LF line endings in the repo but set to
`text` mode in `.gitattributes` so it can be checked out with CRLF line
endings on Windows to match what the Visual Studio `.resx` editor
expects.
The `.resx` file currently uses the
`<Generator>ResXFileCodeGenerator</Generator>` Visual Studio IDE
mechanism to generate a `Resources.Designer.cs` file that provides C#
property names for the string resources. Visual Studio updates the file
each time a change is saved to the corresponding `.resx` file. This is
the approach used by the nonpublic xamarin/designer and
xamarin/XamarinVS repos.
In the future, if `Xamarin.Android.Build.Tasks.csproj` is converted to a
[short-form project][2], it would probably be best to add a dependency
on dotnet/arcade and switch to using the [`GenerateResxSource`
mechanism][3] instead of `ResXFileCodeGenerator`. That would match what
dotnet/sdk does.
This commit leaves the message code `XA4214` as a string literal for
now. This differs from what dotnet/sdk and microsoft/msbuild do. They
instead include the message code as part of the string resource in the
`.resx` file. That might sometimes provide useful additional context
for the translation team, but it also requires using a different set of
logging methods from `Microsoft.Build.Utilities.TaskLoggingHelper`, and
for the existing messages in Xamarin.Android, the message codes don't
seem like they will be too useful for the translation team anyway.
The [dotnet/xliff-tasks][0] tasks and targets find `.resx` files in a
project, generate or update corresponding `.xlf` [XLIFF][1] files as
needed, and then build satellite assemblies from the `.xlf` files.
Using xliff-tasks involves a few steps:
1. Add the dotnet-eng Azure DevOps NuGet package feed or the
dotnet-core MyGet NuGet package feed to `NuGet.config`. This commit
uses dotnet-eng because that seems to be the more up-to-date
recommendation, based on the [dotnet/arcade README][4].
2. Add the XliffTasks NuGet package to the project to localize.
3. Set `$(UpdateXlfOnBuild)` to `true` for the project when building
locally, but not when building on CI. This follows the strategy
suggested in the [xliff-tasks README][5]:
Many teams using `XliffTasks` default `UpdateXlfOnBuild` to true
for local developer builds, but leave it off for CI builds. This
way the .xlf files are automatically updated as the developer
works, and the CI build will fail if the developer forgets to
include the changes to the .xlf files as part of their PR. This
way the .xlf files are always in sync with the source files, and
can be handed off to a localization team at any time.
This commit sets the property globally via `Configuration.props` to
help make it easily visible to contributors.
4. Build the project to generate the initial set of `.xlf` files.
5. Add the generated `.xlf` files to source control.
6. Update the targets for the installer packages so that they include
the satellite assemblies generated by XliffTasks.
In the future, if `Xamarin.Android.Build.Tasks.csproj` is converted to a
short-form project, it would probably be best to add a dependency on
dotnet/arcade, set `$(UsingToolXliff)` to `true`, and then undo steps
1-3 since dotnet/arcade takes care of those steps automatically.
I locally verified that the satellite assemblies were included in the
expected locations in both the Windows and macOS installers with this
commit in place.
I also locally verified that MSBuild used the text from
`Resources.fr.xlf` for the XA4214 warning if I modified
`GenerateJavaStubs.Run()` to set both
`Thread.CurrentThread.CurrentCulture()` and
`Thread.CurrentThread.CurrentUICulture()` to
`new CultureInfo ("fr-FR")`.
[0]: https://github.com/dotnet/xliff-tasks
[1]: http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html
[2]: https://docs.microsoft.com/visualstudio/msbuild/how-to-use-project-sdk
[3]: https://github.com/dotnet/arcade/blob/e67d9f098029ebecedf11012a749b532d68ad2a9/Documentation/ArcadeSdk.md#generateresxsource-bool
[4]: https://github.com/dotnet/arcade/blob/2c6db6ee8d8adeb2e8ccc1485e6780635890e419/README.md#getting-started
[5]: https://github.com/dotnet/xliff-tasks/blob/91369f6f0585fa092eddfa6c169b7f68174eb763/README.md#updating-xlf-files
<value>The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</value>
122
+
<comment>{0} - The managed type name
123
+
{1} - Comma-separated list of all the assemblies where the managed type exists</comment>
124
+
</data>
125
+
<dataname="XA4214_Result"xml:space="preserve">
126
+
<value>References to the type `{0}` will refer to `{0}, {1}`.</value>
127
+
<comment>The phrase "`{0}, {1}`" does not need to be translated.
128
+
{0} - The managed type name
129
+
{1} - The the name of the library that contains the type</comment>
<source>The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</source>
7
+
<targetstate="new">The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</target>
8
+
<note>{0} - The managed type name
9
+
{1} - Comma-separated list of all the assemblies where the managed type exists</note>
10
+
</trans-unit>
11
+
<trans-unitid="XA4214_Result">
12
+
<source>References to the type `{0}` will refer to `{0}, {1}`.</source>
13
+
<targetstate="new">References to the type `{0}` will refer to `{0}, {1}`.</target>
14
+
<note>The phrase "`{0}, {1}`" does not need to be translated.
15
+
{0} - The managed type name
16
+
{1} - The the name of the library that contains the type</note>
<source>The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</source>
7
+
<targetstate="new">The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</target>
8
+
<note>{0} - The managed type name
9
+
{1} - Comma-separated list of all the assemblies where the managed type exists</note>
10
+
</trans-unit>
11
+
<trans-unitid="XA4214_Result">
12
+
<source>References to the type `{0}` will refer to `{0}, {1}`.</source>
13
+
<targetstate="new">References to the type `{0}` will refer to `{0}, {1}`.</target>
14
+
<note>The phrase "`{0}, {1}`" does not need to be translated.
15
+
{0} - The managed type name
16
+
{1} - The the name of the library that contains the type</note>
<source>The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</source>
7
+
<targetstate="new">The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</target>
8
+
<note>{0} - The managed type name
9
+
{1} - Comma-separated list of all the assemblies where the managed type exists</note>
10
+
</trans-unit>
11
+
<trans-unitid="XA4214_Result">
12
+
<source>References to the type `{0}` will refer to `{0}, {1}`.</source>
13
+
<targetstate="new">References to the type `{0}` will refer to `{0}, {1}`.</target>
14
+
<note>The phrase "`{0}, {1}`" does not need to be translated.
15
+
{0} - The managed type name
16
+
{1} - The the name of the library that contains the type</note>
<source>The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</source>
7
+
<targetstate="new">The managed type `{0}` exists in multiple assemblies: {1}. Please refactor the managed type names in these assemblies so that they are not identical.</target>
8
+
<note>{0} - The managed type name
9
+
{1} - Comma-separated list of all the assemblies where the managed type exists</note>
10
+
</trans-unit>
11
+
<trans-unitid="XA4214_Result">
12
+
<source>References to the type `{0}` will refer to `{0}, {1}`.</source>
13
+
<targetstate="new">References to the type `{0}` will refer to `{0}, {1}`.</target>
14
+
<note>The phrase "`{0}, {1}`" does not need to be translated.
15
+
{0} - The managed type name
16
+
{1} - The the name of the library that contains the type</note>
0 commit comments