Localize Blazor strings that the text-translate TagHelper can't reach (#7423)
What changed, and why it matters
This commit fixes a localization bug in BTCPay Server's Blazor user interface components. Some text strings were not being translated into the user's chosen language because they relied on a translation mechanism that only works in older Razor view files, not in newer Blazor components. The change switches those strings to use Blazor-compatible localization and registers the new translatable phrases in the default translation file. There is no security impact.
No security action required. Treat as a routine localization fix.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit replaces text-translate="true" attributes with @StringLocalizer[...] / @ui.StringLocalizer[...] calls in three Blazor .razor files (NotificationsDropDown.razor, PosLoginCode.razor, XPubSelect.razor). The text-translate/html-translate attributes are processed by TranslateTagHelper, an MVC TagHelper that does not execute inside Blazor components, causing English text to be rendered unconditionally. The commit also adds the affected English strings to Translations.Default.cs so they can be translated. PosLoginCode.razor additionally injects IStringLocalizer. This is a pure localization/UX fix with no security-relevant code changes.
Changed components
BTCPayServer/Blazor/NotificationsDropDown.razorBTCPayServer/Blazor/PosLoginCode.razorBTCPayServer/Blazor/VaultBridge/Elements/XPubSelect.razorBTCPayServer/Plugins/Translations/Translations.Default.csInspect captured patch +14 / −7
diff --git a/BTCPayServer/Blazor/NotificationsDropDown.razor b/BTCPayServer/Blazor/NotificationsDropDown.razor
index 9cd3436..fae61da 100644
--- a/BTCPayServer/Blazor/NotificationsDropDown.razor
+++ b/BTCPayServer/Blazor/NotificationsDropDown.razor
@@ -32,10 +32,10 @@
</button>
<div class="dropdown-menu text-center" id="NotificationsDropdown" aria-labelledby="NotificationsHandle">
<div class="d-flex gap-3 align-items-center justify-content-between py-3 px-4 border-bottom border-light">
- <h5 class="m-0" text-translate="true">Notifications</h5>
+ <h5 class="m-0">@StringLocalizer["Notifications"]</h5>
@if (HasUnseenNotifications)
{
- <a class="btn btn-link p-0" @onclick="MarkAllAsSeen" id="NotificationsMarkAllAsSeen" text-translate="true">Mark all as seen</a>
+ <a class="btn btn-link p-0" @onclick="MarkAllAsSeen" id="NotificationsMarkAllAsSeen">@StringLocalizer["Mark all as seen"]</a>
}
</div>
<div id="NotificationsList" v-pre>
@@ -60,11 +60,11 @@
}
else
{
- <div class="px-4 py-4 text-start text-muted" text-translate="true">No new notifications</div>
+ <div class="px-4 py-4 text-start text-muted">@StringLocalizer["No new notifications"]</div>
}
</div>
<div class="p-3 border-top border-light">
- <a href="@NotificationsUrl" text-translate="true">View all</a>
+ <a href="@NotificationsUrl">@StringLocalizer["View all"]</a>
</div>
</div>
</div>
diff --git a/BTCPayServer/Blazor/PosLoginCode.razor b/BTCPayServer/Blazor/PosLoginCode.razor
index bfc4ba2..ee77ec6 100644
--- a/BTCPayServer/Blazor/PosLoginCode.razor
+++ b/BTCPayServer/Blazor/PosLoginCode.razor
@@ -3,14 +3,16 @@
@using BTCPayServer.Plugins.PointOfSale.Controllers
@using Microsoft.AspNetCore.Mvc
@using Microsoft.AspNetCore.Routing
+@using Microsoft.Extensions.Localization
@inject LinkGenerator LinkGenerator
+@inject IStringLocalizer StringLocalizer
@if (UserEmails?.Any() is true)
{
<div @attributes="Attrs" class="@CssClass">
- <label for="SignedInUser" class="form-label" text-translate="true">Signed in user</label>
+ <label for="SignedInUser" class="form-label">@StringLocalizer["Signed in user"]</label>
<select id="SignedInUser" class="form-select" @onchange="@OnUserChanged">
- <option value="" text-translate="true">None, just open the URL</option>
+ <option value="">@StringLocalizer["None, just open the URL"]</option>
@foreach (var u in UserEmails)
{
<option value="@u.Key">@u.Value</option>
diff --git a/BTCPayServer/Blazor/VaultBridge/Elements/XPubSelect.razor b/BTCPayServer/Blazor/VaultBridge/Elements/XPubSelect.razor
index 0a4aec1..2566765 100644
--- a/BTCPayServer/Blazor/VaultBridge/Elements/XPubSelect.razor
+++ b/BTCPayServer/Blazor/VaultBridge/Elements/XPubSelect.razor
@@ -18,7 +18,7 @@
</select>
</div>
<div class="form-group">
- <label for="accountNumber" class="form-label" text-translate="true">Account</label>
+ <label for="accountNumber" class="form-label">@ui.StringLocalizer["Account"]</label>
<input id="accountNumber" @bind="AccountNumber" class="form-control" name="accountNumber" type="number" min="0" step="1"
style="max-width:12ch;" />
</div>
diff --git a/BTCPayServer/Plugins/Translations/Translations.Default.cs b/BTCPayServer/Plugins/Translations/Translations.Default.cs
index 6ccfb0e..e431ea9 100644
--- a/BTCPayServer/Plugins/Translations/Translations.Default.cs
+++ b/BTCPayServer/Plugins/Translations/Translations.Default.cs
@@ -1008,6 +1008,7 @@ namespace BTCPayServer.Plugins.Translations
"Manually enter your 12 or 24 word recovery seed.": "",
"Map specific domains to specific apps": "",
"Mapped Value": "",
+ "Mark all as seen": "",
"Mark as a test account": "",
"Mark as already paid": "",
"Mark as awaiting payment": "",
@@ -1097,6 +1098,7 @@ namespace BTCPayServer.Plugins.Translations
"No languages available to install.": "",
"No matches found": "",
"No matching payment method": "",
+ "No new notifications": "",
"No payment handler found for this payment method": "",
"No payment request related email rules have been configured for this store.": "",
"No payments have been made yet.": "",
@@ -1123,6 +1125,7 @@ namespace BTCPayServer.Plugins.Translations
"Non-admins can use the Internal Lightning Node for their Store": "",
"Non-admins cannot access the User Creation API Endpoint": "",
"Non-supported state of invoice": "",
+ "None, just open the URL": "",
"None of the selected transaction can be fee bumped": "",
"Normal": "",
"Not all payout methods are supported": "",
@@ -1644,6 +1647,7 @@ namespace BTCPayServer.Plugins.Translations
"Sign transaction": "",
"Sign using our Vault application": "",
"Signatures": "",
+ "Signed in user": "",
"Signed out": "",
"Signer": "",
"Signer key submitted successfully.": "",
@@ -2165,6 +2169,7 @@ namespace BTCPayServer.Plugins.Translations
"via the REST API": "",
"View": "",
"View All": "",
+ "View all": "",
"View all supporters": "",
"View Invite": "",
"View report '{0}'": "",
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.