I hope you don't mind, I just added this as a comment to your blog along with a link to my solution.
I hope you don't mind, I just added this as a comment to your blog along with a link to my solution.
So it is bad news for those people who use validation summaries, and a lot of labour (and possible mistakes) in setting a string on every attribute.
My library gives the best of both. 1 line of manual work, no mistakes, and supports field names + any attribute property placeholders (max length).
It's also not a feasible approach when the format string has values in it, such as
"{0} has a maximum length of {1}."
You'd either have to just output "String is too long" or have a unique string for each unique string length in your app...
The default error messages come from a pre-defined format string that has a placeholder for the member name.
"The {0} field is required".
This is why in your example you have to set the ErrorMessage on every validator - but that then becomes unusable when you use a validation summary...
Well, if you do want to use ValidatorAttribute and have localization. Now it's easy :)
In that case, your scenario can obviously use FluentValidation to localize and not need to worry about Swagger schemas not being updated :)
Ah I see, so you have a shared Contracts project used by both client and server that had data objects and FV validators in - and then you use FV to validate on the client before talking to the API and on the server to validate the request?
I did exactly that, but it was pointless because injecting TranslationService and grabbing TS.Person_FamilyName gave the exact same output as TypeGeneratedFromResxFile.Person_Family_Name
And it didn't work with ValidatorAttribute et al.
So there was just no need for it.
How did you remove the need to get FV restrictions? Did you stop including meta information in the API schema related to validation?
So you don't use ValidationAttribute at all?
Do you generate Swagger API endpoints for your app? If so, how do you get the FV restrictions to show in the API schema?
I removed that as soon as I spotted the fact that using the code-generated static properties still localized to the current user's culture.
Why MS recommend IStringLocalizer<T>, I just don't know.
I wrote an extension to allow LocalizeErrors.GetText(() => Errors.Required) with an Analyzer to check it was on the same type.
I didn't like that so I wrote Roslyn code to automatically create a class for each resx along with properties, and it used StringLocalizer to resolve the text, but...
The problem is you can pass anything in as the string key, so even with nameof() you could use the wrong resource
LocalizeApp[nameof(Resources.Errors.Required)]
You can't add an extension x => x.Required because expressions can't point to static members...
Yes, and that's just a few lines of code in Program.cs too.
You can still use magic strings for keys using MyRes.ResourceManager
I suspect IStringLocalizer<T> was created just so MS could offer blanket advice "don't use statics" for their "pit of success" advice.
This looks like a nice clean solution to a wart on .NET's localization functionality - using Fody to set a default ErrorMessageResourceType and ErrorMessageResourceName (based on the attribute type).
github.com/mrpmorris/Au...
Seems crazy that this is necessary though - am I missing something?!
I removed IStringLocalizer and just used the static members on the generated classes for resx files. In our Blazor Server app it uses the correct language. No idea how, but it does.
@meziantou.net Hi
I wonder if you can help with a Roslyn unit test problem?
Branch = rewrite
Unit test = github.com/mrpmorris/Ro...
When debugging, attributeData.AttributeClass is always `ErrorTypeSymbol`
github.com/mrpmorris/Ro...
But it actually generates code perfectly.
Any ideas?
What kind of download size do you get for a simple Hello World?
Enable long paths in Windows
It means that you don't know, not that you cannot know.