Wrong msgctxt Value for .razor files
Closed this issue · 7 comments
Steps to Reproduce
Note: Using the latest develop version of PoExtractor.
Source Code (CultureSelector.razor)
@using Microsoft.Extensions.Localization
@using System.Globalization
@using Domain
@inject IStringLocalizer<CultureSelector> S
<MudSelect ValueChanged="SetCulture"
T="CultureInfo"
Value="CultureInfo.CurrentUICulture"
Label="@S["Language"]" Placeholder="@S["Please Select"]"
AdornmentIcon="@Icons.Material.Filled.Language"
Style="width:200px; margin-left:10px;">
@foreach (var culture in SupportedUiLanguages.Cultures)
{
<MudSelectItem Value="@culture" T="CultureInfo">@culture.EnglishName</MudSelectItem>
}
</MudSelect>
Command Line Arguments
src translations -l "C#" -t "razor"
Generated POT file
#: Portal.Web\Shared\CultureSelector.razor:11
#. Label="@S["Language"]" Placeholder="@S["Please Select"]"
msgctxt "Portal.Web.Shared.CultureSelector.razor"
msgid "Language"
msgstr ""
Problem Description
The problem is that the msgctxt
has class name + .razor
suffix.
Using OrchardCore.Localization
however expects the context not to have this suffix.
Problem Diagnosis
The RazorMetadataProvider
performs replacement of the file extension. However, it only considers to replace .cshtml
. In the Blazor project, however, the file extension is .razor
.
Relevant code is in method public string GetContext(SyntaxNode node)
.
Note: also see: https://stackoverflow.com/questions/55590605/what-is-the-difference-between-razor-and-cshtml-files
Possible Solutions
- replace multiple file extensions:
.cshtml
and.razor
- replace the file extension no matter what it is. This works whether the file has an extension or not. Only problem would be, if a file has an extension which is not supposed to be one, let's say
foo.bar
, and.bar
is not supposed to be an extension. Don't think that can happen - or would matter much: class names never have a.
, sofoo.bar
would not be a valid context (class name) in the first place.
Is this still a valid bug? or this one #85?
Yes, I'm experiencing both with the latest version 1.0.1 released on 24.01.2023.
Or do you mean I should try out the version from the develop
branch?
Edit: I will try the develop version. I just noticed that the release is more than a year old and there's a recent addition to support for file-scope namespaces - and we're using them.
@hishamco
on develop
, the first problem with the missing class name is fixed.
Texts in the razor templates are still reported with a msgctxt
of ....razor. Tomorrow I'll verify if this actually is a problem and OrchardCore.Localization uses a different msgctxt
- or not.
I'm waiting, otherwise please write a failing unit test, so I can fix the issue
For completeness sake here a copy of the original post, where I thought there was more problems - but actually 2 out of 3 are resolved in the upcoming .net 8 based version:
See these examples:
#: Portal.Web\Localization\CommonStrings.cs:11
#. public string SaveChanges => S["Save Changes"];
msgctxt "Portal.Web.Localization."
msgid "Save Changes"
msgstr ""
#: Portal.Web\Pages\Picos\LoadManagement\Multilevel\MultilevelErrorMapper.cs:63
#. return S["Not found"];
msgctxt "Portal.Web.Pages.Picos.LoadManagement.Multilevel.MultilevelErrorMapper"
msgid "Not found"
msgstr ""
#: Portal.Web\Shared\CultureSelector.razor:11
#. Label="@S["Language"]" Placeholder="@S["Please Select"]"
msgctxt "Portal.Web.Shared.CultureSelector.razor"
msgid "Language"
msgstr ""
You can see that the first does not include the class name in the msgctxt
while the second does.
The third one has the class name + ".razor" suffix.
I suspect that the msgctxt
is generated from the filename/file path, not the actual type name?
Note that passing -t "razor"
or leaving it out does not change anything about the generated *.pot file.
CommonStrings.cs
public class CommonStrings(
IStringLocalizer<CommonStrings> s)
{
// ReSharper disable once InconsistentNaming required by OrchardCoreContrib
readonly IStringLocalizer S = s;
public string Ok => S["OK"];
public string SaveChanges => S["Save Changes"];
public string Cancel => S["Cancel"];
}
MultilevelErrorMapper.cs
public class MultilevelErrorMapper
{
// ReSharper disable once InconsistentNaming required by PoExtractor
readonly IStringLocalizer S;
public MultilevelErrorMapper(
IStringLocalizer<MultilevelErrorMapper> s)
{
S = s;
}
LocalizedString MapNotFound(
NotFound _)
{
return S["Not found"];
}
}
CultureSelector.razor
@using Microsoft.Extensions.Localization
@using System.Globalization
@using Domain
@inject IStringLocalizer<CultureSelector> S
<MudSelect ValueChanged="SetCulture"
T="CultureInfo"
Value="CultureInfo.CurrentUICulture"
Label="@S["Language"]" Placeholder="@S["Please Select"]"
AdornmentIcon="@Icons.Material.Filled.Language"
Style="width:200px; margin-left:10px;">
@foreach (var culture in SupportedUiLanguages.Cultures)
{
<MudSelectItem Value="@culture" T="CultureInfo">@culture.EnglishName</MudSelectItem>
}
</MudSelect>
@hishamco
Sorry for the delay - I was super busy at work.
I have now investigated the issue and it's just the fact that Razor support is broken when the razor file does not have a file ending of .cshtml
. I have updated the issue entry (first post) to reflect that and have given more information there, including steps to reproduce. The issue should be rather trivial to fix.
If you want me to, I can provide a PR, but would like to request guidance from you as to which solution to choose.
Like I wrote in the opening post I see two easy solutions:
- replace
.cshtml
and.razor
with string.empty. This one is safe, but of course, if another extension is used, it doesn't work. - replace any file extension, no matter what it is. This one stops working when the file has a name of
foo.bar
but.bar
is not supposed to be an extension... so I think it's safe, too, and simpler, too. So I would propose to use this.
IMHO supporting .razor
makes sense to me