There might be other occurences, OrchardCore.Users/Controllers/AdminController.cs uses SelectListItems with .Value on an IHtmlLocalizer. They will be double-encoded.
This is odd, I think we fixed this before, seems some new changes bring the issue again :)
We have things similar issues for sure, but some are still present.
I will handle this, but I'm trying to fixing a weird localization issue
For infos, just did the following test
@{
var test = T["Your {0} draft has been saved.", "ééé"];
}
@Html.ActionLink(test.Value, "List", "Admin", new { area = "OrchardCore.Contents" }))
<a href="#">@test</a>
<div attr1 ="@test" attr2="@test.Value">
@test
@test.Value
</div>
<a href="/Admin/Contents/ContentItems">Votre brouillon de {0} a été enregistré.</a>)
<a href="#">Votre brouillon de ééé a été enregistré.</a>
<div attr1 ="Votre brouillon de ééé a été enregistré." attr2="Votre brouillon de {0} a été enregistré.">
Votre brouillon de ééé a été enregistré.
Votre brouillon de {0} a été enregistré.
</div>
As we can see, when using a LocalizedHtmlString (not its .Value) the translated base string is not encoded, only the passed arguments are resolved and then encoded.
So if there is no argument, using .Value is not exactly a double encoding issue, the issue is that the base string will be encoded whereas it would not have been.
If there are arguments, the other issue is that .Value is the translated string but before any formatting, e.g still including a {0}. So here it is not exactly a double encoding issue, the issue is that arguments are not resolved.
Anyway the result is the same, a LocalizedHtmlString can be used in places where we can use it as is, but not in places where we need to use its .Value for some castings, knowing that the concrete encoding will happen when calling on it WriteTo(), most of the time through the @ directive in a razor file.
Thanks for the info @jtkech, seems I will write some unit tests for that, also I will look why the {0} still included in some cases
@jtkech not sure you are exposing the bug. Call .Value and assign it to a string variable (like the code does), then call @ on this variable.
Or maybe you found another bug, for which I thought I had added specific unit tests.
not sure you are exposing the bug. Call .Value and assign it to a string variable (like the code does), then call @ on this variable.
It is the same, here the main thing is that the based string is not encoded, only the passed args if any, i looked at the LocalizedHtmlString code that uses an HtmlFormattableString that internally uses an EncodingFormatProvider that seems to only encode arguments.
This allows to use <h3>Some text with a {0} argument</h3> where only the passed argument is encoded. I don't say it is good, this is just what i saw when i tried it.
Anyway the rule is the same, e.g don't pass the LocalizedHtmlString.Value to an html helper, don't use @myLocalizedHtmlString.Value. Otherwise the arguments if any will not be resolved (not an encoding issue but still an issue), and the base string will be encoded which seems to not be intended to be done.
Should we close ? https://github.com/OrchardCMS/OrchardCore/pull/4750#issuecomment-565519632
Most helpful comment
4750 was just about declaration / naming conventions