Skip to content
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

UWP app en-US unit abbreviation resources not found for units with multiple languages defined #1307

Closed
ms-sio opened this issue Aug 15, 2023 · 4 comments · Fixed by #1311
Closed
Labels

Comments

@ms-sio
Copy link
Contributor

ms-sio commented Aug 15, 2023

Describe the bug
UWP app unable to find default / en-US abbreviation cache resources when multiple languages are defined in .restext files. This results in ToString() not including the unit abbreviations for those quantity types. Warnings are also generated on build:

GENERATEPROJECTPRIFILE : warning : PRI257: 0xdef00522 - Resources found for language(s) 'fr-ca,ru-ru,zh-cn' but no resources found for default language(s): 'en-US'. Change the default language or qualify resources with the default language. GENERATEPROJECTPRIFILE : warning : PRI263: 0xdef01051 - No default or neutral resource given for 'UnitsNet.GeneratedCode.Resources.Mass/Picograms'. The application may throw an exception for certain user configurations when retrieving the resources. ...

To Reproduce

  1. Create a blank UWP app and add UnitsNet nuget package

  2. Add a few quantities with and without multiple abbreviation languages defined in resources

  3. Observe build warnings and inspect ToString() output for each

     public MainPage()
     {
         this.InitializeComponent();
    
         // Multi-lang
         var press = new Pressure(123, PressureUnit.Atmosphere).ToString();  // Outputs 123
         var len = new Length(123, LengthUnit.Meter).ToString();  // Outputs 123
         var speed = new Speed(123, SpeedUnit.MeterPerSecond).ToString();  // Outputs 123
    
         // Single-lang
         var amplitude = new AmplitudeRatio(123, AmplitudeRatioUnit.DecibelVolt).ToString();  // Outputs 123 dBV
         var temp = new Temperature(123, TemperatureUnit.DegreeCelsius).ToString();  // Outputs 123 °C
         var current = new ElectricCurrent(123, ElectricCurrentUnit.Milliampere).ToString();  // Outputs 123 mA
     }
    

Additional context
The issue seems to be related to the way makepri.exe attempts to split resources into different folders based on language/region. GenerateResourceFiles() in UnitsNetGenerator omits the "en-US" culture in the filename for generated .restext files so the workaround of using the AppxDefaultResourceQualifiers configuration and setting Language=en-us,fr-ca,ru-ru,zh-cn in the .csproj does not work.

Possible Resolution
Include "en-US" culture version of resource files.

@ms-sio ms-sio added the bug label Aug 15, 2023
@angularsen
Copy link
Owner

I don't have much experience with UWP so I can't help with that.

It may be an option to have codegen generate en-US files, but if that means duplicating the default localization .restext files then it feels like the wrong solution.

In my experience with ResourceManager and .resx files, there was always a default culture that localization fell back to if the requested culture did not have a localization.

Does it not work like that for UWP?
Is there a best practice for UWP or some configuration to tweak?
I think we need to better understand how this differs for UWP vs other .NET apps.

@ms-sio
Copy link
Contributor Author

ms-sio commented Aug 21, 2023

I'm having a difficult time finding docs that specifically mention the differences between UWP and other .NET projects in this regard, but it seems to be a known issue. Some posts I found mention it has to do with the old style (non-SDK) csproj files used in UWP projects and their interaction with makepri and the Win SDK. For these projects, it seems like makepri.exe gets confused while splitting resources when there is a mixture of resource files with and without culture specifiers in the filenames. UWP projects cannot be easily upgraded to the new SDK-style csproj unfortunately.

Resource files without language specifiers are not found if other matching resource files with specified cultures are included. Inspecting the output of makepri shows the default resources are missing only for those with alternate languages defined when building a test UWP project. Units that only have a single corresponding resource file without any alternate languages defined work just fine.

There is a way to configure a UWP app to disable auto-splitting of resources and build the resources into the app package (link), but this method does not work either since it requires explicitly listing the resources in order of priority. Since "en-US" versions of resources are not generated then they cannot be explicity listed in the csproj for this method.

I think part of the issue is that the assembly neutral language in the UnitsNet project is not defined. One potential solution that I've seen suggested is to set the assembly neutral language for the project explicitly and include the corresponding resources. I think this may be an acceptable solution since the UnitsNet project seems to already be using "en-US" as its baseline for resources (as of the recent changes made to the unit abbreviations resources in v5.22.0).

Possible Resolution
Currently, UnitsNetGenerator.cs looks for "en-US" culture and omits the specifier from the resource filename when generating default .restext files as seen here:

foreach(var culture in cultures)
{
var fileName = culture.Equals("en-US", System.StringComparison.InvariantCultureIgnoreCase) ?
$"{resourcesDirectory}/{quantity.Name}.restext" :
$"{resourcesDirectory}/{quantity.Name}.{culture}.restext";
using var writer = File.CreateText(fileName);

My suggestion would be to get rid of the code that omits the "en-US" specifier from the resource filenames and set the assembly neutral language for the UnitsNet project to "en-US" instead. This explicitly defines which neutral resources should be used while solving the issue for UWP projects (and possibly other older style .csproj files) while avoiding duplication of resource files.

@angularsen
Copy link
Owner

I think that sounds like a reasonable solution, would you be interested in attempting a pull request and verify it works for both UWP and a regular .NET console app?

@ms-sio
Copy link
Contributor Author

ms-sio commented Aug 30, 2023

After further testing it looks like only the neutral language needs to be set to fix the issue for UWP apps. I have also tested the change with a .NET core console app and WPF app. Pull request has been submitted (#1311).

angularsen pushed a commit that referenced this issue Sep 1, 2023
Fixes #1307

Set assembly neutral language to `en-US` for UnitsNet project
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants