-
Notifications
You must be signed in to change notification settings - Fork 31
Localization #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Localization #96
Conversation
brendanzagaeski
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a bunch for setting this up! I'll leave a first few comments for this initial draft in case they'll help with the next steps for the PR.
At the moment, the Azure Pipelines build on Windows is failing with:
The nuget command failed with exit code(1) and error(NU1101: Unable to find package XliffTasks. No packages exist with this id in source(s): NuGetOrg
NU1101: Unable to find package XliffTasks. No packages exist with this id in source(s): NuGetOrg
Errors in D:\a\1\s\src\Xamarin.Android.Tools.AndroidSdk\Xamarin.Android.Tools.AndroidSdk.csproj
NU1101: Unable to find package XliffTasks. No packages exist with this id in source(s): NuGetOrg
Errors in D:\a\1\s\tests\Xamarin.Android.Tools.AndroidSdk-Tests\Xamarin.Android.Tools.AndroidSdk-Tests.csproj
NU1101: Unable to find package XliffTasks. No packages exist with this id in source(s): NuGetOrg)
One way to resolve this is to specify the feedsToUse and nugetConfigPath inputs for the NuGetCommand@2 Azure Pipelines task:
diff --git a/azure-pipelines.yaml b/azure-pipelines.yaml
index 6b2a147..7a55b27 100644
--- a/azure-pipelines.yaml
+++ b/azure-pipelines.yaml
@@ -31,6 +31,8 @@ jobs:
displayName: 'NuGet Restore'
inputs:
restoreSolution: Xamarin.Android.Tools.sln
+ feedsToUse: config
+ nugetConfigPath: NuGet.config
- task: MSBuild@1
displayName: 'Build solution Xamarin.Android.Tools.sln'
inputs:This seems like a nice approach for this case.
Another option would be to specify the full NuGet command to run, like in the latest version of xamarin-android's setup-test-environment.yaml.
|
|
||
| <PropertyGroup> | ||
| <XlfLanguages>cs;de;es;fr;it;ja;ko;pl;pt-BR;ru;tr;zh-Hans;zh-Hant</XlfLanguages> | ||
| <UpdateXlfOnBuild Condition="'$(RunningOnCI)' != 'true'">true</UpdateXlfOnBuild> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The xamarin-android-tools-ci pipeline did not yet have the RunningOnCI variable defined under the Variables button, so I have just added it to align with the convention followed by the pipelines for the other xamarin-android repositories like xamarin-android itself, Java.Interop, and monodroid.
No changes are needed in the PR to account for this. I just wanted to mention it here for reference.
src/Xamarin.Android.Tools.AndroidSdk/Xamarin.Android.Tools.AndroidSdk.csproj
Outdated
Show resolved
Hide resolved
| throw new ArgumentNullException (nameof (homePath)); | ||
| if (!Directory.Exists (homePath)) | ||
| throw new ArgumentException ("Not a directory", nameof (homePath)); | ||
| throw new ArgumentException ("XamarinAndroidTools_XAT0008", nameof (homePath)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this use Resources.ResourceManager.GetString("XamarinAndroidTools_XAT0008")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Sorry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added one more which was missed.
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@brendanzagaeski's comment raises a pre-existing-yet-unanswered question around error code management: How should they be managed? The interaction between xamarin/Java.Interop & xamarin/xamarin-android has the "same" problem/scenario: Similar-but-different, should the "leaf methods" know about error codes in the first place? With this "philosophical thinking" in place, I think the xamarin-android-tools repo shouldn't know, care, or otherwise worry about error codes. I think that should be handled by the callers, e.g. the However, this poses a different question: different errors should get different codes. How should this "difference" be communicated? In the case of xamarin-android-tools, there is no difference; there is only one use of % git grep TraceLevel.Error
src/Xamarin.Android.Tools.AndroidSdk/AndroidSdkInfo.cs: case TraceLevel.Error:
src/Xamarin.Android.Tools.AndroidSdk/Sdks/AndroidSdkUnix.cs: logger (TraceLevel.Error, "Could not load monodroid configuration file");That doesn't answer how things should work in e.g. Java.Interop, but for here-and-now, we don't need to worry about error codes at all. |
|
Note that currently this PR adds several NRT warnings to the build: https://dev.azure.com/xamarin/public/_build/results?buildId=27103&view=results. |
|
Context: dotnet/android@0342fe5 |
…ed_localization This merge is largely to address some of the nullable reference type warnings that were being emitted.
Instead of `Resources.ResourceManager.GetString("NAME")`, use
`Resources.NAME`. This promotes type safety, ensuring that we don't
"typo" resource names, and use resources that (should) exist.
Review and replace the `<comment/>` values within `Resourdces.resx`,
so that they're (hopefully) useful values for the translators.
Re-run `/t:UpdateXlf` so that the `Resources.*.xlf` files have all the
strings from `Resources.resx`.
Open Visual Studio for Mac and "update" `Resources.resx` to cause it
to regenerate `Resource.Designer.cs`, as it was missing the
`XamarinAndroidTools_XAT0017` resource.
Remove `XamarinAndroidTools_XAT0012`, as it's not for localization:
https://github.com/xamarin/xamarin-android-tools/pull/96/files#r493056022
|
@brendanzagaeski: Question: how do we make the generated |
|
Commit message for squash-and-merge review: Context: https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1009374/
Context: https://github.com/xamarin/xamarin-android/commit/0342fe5698b86e21e36c924732ff135b9a87e4af
Localize error, warning, and exception messages produced by
`Xamarin.Android.Tools.AndroidSdk.dll`.
We will be following the [.NET Resource Localization pattern][0] and
generating satellite assemblies using [`.resx` files][1], in particular
`src/Xamarin.Android.Tools.AndroidSdk/Properties/Resources.resx`.
`Resources.resx` is an XML file, and will contain `/root/data`
elements in which `//data/@name` will start with the
xamarin-android-tools error or warning code, and `//data/value` will
be the error or warning message:
<root>
<data name="XamarinAndroidTools_XAT0001" xml:space="preserve">
<value>App manifest does not have 'manifest' root element</value>
<comment>The following are literal names and should not be translated: manifest</comment>
</data>
</root>
An optional `//data/comment` element may be provided to describe the
meaning within the `//data/value` element to translators.
When using Visual Studio or Visual Studio for Mac, changes to
`Resrouces.resx` will cause `Resources.Designer.cs` to be updated:
namespace Xamarin.Android.Tools.AndroidSdk.Properties {
internal partial class Resources {
internal static string XamarinAndroidTools_XAT0001 {
get => ...
}
}
}
The `Resources` members should be used to obtain all strings for use
in `logger()` and `throw new …()` calls:
logger (TraceLevel.Warning, string.Format (Resources.XamarinAndroidTools_XAT0013, path, locator, e.Message));
throw new ArgumentException (Resources.XamarinAndroidTools_XAT0001, nameof (doc));
When an MSBuild error or warning code is used with more than one
output string, then a semantically meaningful suffix should be used
to distinguish between the two.
Note that this infrastructure does not interoperate with C#6 string
interpolation. Any error or warning messages currently using C#6
string interpolation will need to use .NET 1.0-style format strings.
Our translation team doesn't work directly with `.resx` files.
Instead, the translation team works with [XLIFF files][2].
`Resources.resx` is converted into a set of
`src/Xamarin.Android.Build.Tasks/Properties/xlf/Resources.*.xlf`
files via `XliffTasks.targets` from the [dotnet/xliff-tasks][3] repo.
The `Resources.*.xlf` files should be automatically updated whenever
`Resources.resx` is updated.
[0]: https://docs.microsoft.com/dotnet/framework/resources/index
[1]: https://docs.microsoft.com/dotnet/framework/resources/creating-resource-files-for-desktop-apps#resources-in-resx-files
[2]: http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html
[3]: https://github.com/dotnet/xliff-tasks |
|
To make the generated members -<Generator>PublicResXFileCodeGenerator</Generator>
+<Generator>ResXFileCodeGenerator</Generator> |
brendanzagaeski
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The two other logger() calls mentioned previously are not yet localizable:
src/Xamarin.Android.Tools.AndroidSdk/Sdks/AndroidSdkUnix.cs:235: logger (TraceLevel.Error, "Could not load monodroid configuration file");
src/Xamarin.Android.Tools.AndroidSdk/Sdks/AndroidSdkWindows.cs:117: logger (TraceLevel.Warning, $"The directory `{path}`, via locator `{locator}`, is not a valid JDK directory: {e.Message}");
I believe it will make sense to include those in this PR since they are surfaced as MSBuild messages in the same way as the logger() call in JdkInfo. Thanks!
Wording brainstorming:
-
For:
src/Xamarin.Android.Tools.AndroidSdk/Sdks/AndroidSdkUnix.cs:235: logger (TraceLevel.Error, "Could not load monodroid configuration file");I'll suggest something like:
<data name="InvalidJdkPathConfigFile" xml:space="preserve"> <value>An exception occurred while loading the Java SDK path configuration file '{0}'. Ensure that the file is a valid XML file. Exception: {1}</value> <comments>{0} - The path of the invalid file {1} - The exception message of the associated exception</comments> </data>
-
For:
src/Xamarin.Android.Tools.AndroidSdk/Sdks/AndroidSdkWindows.cs:117: logger (TraceLevel.Warning, $"The directory `{path}`, via locator `{locator}`, is not a valid JDK directory: {e.Message}");This one can use the same
Resources.InvalidJdkDirectoryresource as used inJdkInfo.
Thanks!
Addresses: * #96 (comment) * #96 (comment) * #96 (comment)
Context: #96 (review) Add the following error messages: * `FailedToChangeFileSystemOwnership` * `InvalidMonodroidConfigFile_path_message` Additionally, rename `InvalidJdkDirectory` to `InvalidJdkDirectory_path_locator_message` as a "trial balloon": one of my "foibles" with localization is that the localizations frequently use string formats -- {0}, {1}, etc. -- but it's not obvious how many parameters a message takes unless the message is in front of you. Thus, an idea: what if we "Hungarian-notationed" things so that the number of parameters was encoded into the descriptor? This could be e.g. a `_3` suffix -- "takes 3 parameters" -- but that's ugly. We can build on this and instead encode *semantics* for what each parameter is. Thus, `InvalidJdkDirectory_path_locator_message`: it takes three parameters, a *path*, a *locator*, and a *message*: logger (TraceLevel.Warning, string.Format (Resources.InvalidJdkDirectory, path, locator, e.Message)); // vs. logger (TraceLevel.Warning, string.Format (Resources.InvalidJdkDirectory_path_locator_message, path, locator, e.Message)) I think this makes things a bit more obvious.
Context: #96 (review) Add the following error messages: * `FailedToChangeFileSystemOwnership` * `InvalidMonodroidConfigFile_path_message` Additionally, rename `InvalidJdkDirectory` to `InvalidJdkDirectory_path_locator_message` as a "trial balloon": one of my "foibles" with localization is that the localizations frequently use string formats -- {0}, {1}, etc. -- but it's not obvious how many parameters a message takes unless the message is in front of you. Thus, an idea: what if we "Hungarian-notationed" things so that the number of parameters was encoded into the descriptor? This could be e.g. a `_3` suffix -- "takes 3 parameters" -- but that's ugly. We can build on this and instead encode *semantics* for what each parameter is. Thus, `InvalidJdkDirectory_path_locator_message`: it takes three parameters, a *path*, a *locator*, and a *message*: logger (TraceLevel.Warning, string.Format (Resources.InvalidJdkDirectory, path, locator, e.Message)); // vs. logger (TraceLevel.Warning, string.Format (Resources.InvalidJdkDirectory_path_locator_message, path, locator, e.Message)) I think this makes things a bit more obvious.
fd23187 to
0cb78c0
Compare
Add the automatic changes that Visual Studio makes when saving the resource files so there won't be any need to worry about them getting included unintentionally as part of an unrelated future change to the `.resx` file.
|
/azp run |
|
No pipelines are associated with this pull request. |
brendanzagaeski
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved! I pushed one more small commit to update the generated files, so those should be all set now.
It'll probably be good to get the build pipeline to run once more on this PR to be careful before merging, but it looks good locally, so I think that'll build without problems if we can get it to trigger.
|
I manually triggered the pipeline for this branch via the Azure Pipelines UI. That seemed to allow it to run correctly, including having |
Oops.
No description provided.