Add parts of the UI to translate (#6119)

This commit is contained in:
Nicolas Dorier 2024-07-25 22:46:02 +09:00 committed by GitHub
parent 50dafd2452
commit 94760792af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
96 changed files with 381 additions and 192 deletions

View File

@ -18,6 +18,7 @@ using NBitcoin;
using NBitcoin.RPC;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.Extensions;
using OpenQA.Selenium.Support.UI;
using Xunit;

View File

@ -2063,7 +2063,7 @@ namespace BTCPayServer.Tests
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.FindElement(By.Id("Amount")).Clear();
s.Driver.FindElement(By.Id("Amount")).SendKeys("99.0");
@ -2108,7 +2108,7 @@ namespace BTCPayServer.Tests
await s.Server.ExplorerNode.GenerateAsync(1);
await s.FundStoreWallet(denomination: 50.0m);
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.FindElement(By.Id("Amount")).Clear();
s.Driver.FindElement(By.Id("Amount")).SendKeys("99.0");
@ -2122,7 +2122,7 @@ namespace BTCPayServer.Tests
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP2");
s.Driver.FindElement(By.Id("Amount")).Clear();
s.Driver.FindElement(By.Id("Amount")).SendKeys("100.0");
@ -2225,7 +2225,7 @@ namespace BTCPayServer.Tests
s.GenerateWallet("BTC", "", true, true);
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("External Test");
s.Driver.FindElement(By.Id("Amount")).Clear();
s.Driver.FindElement(By.Id("Amount")).SendKeys("0.001");
@ -2276,7 +2276,7 @@ namespace BTCPayServer.Tests
//Currently an onchain wallet is required to use the Lightning payouts feature..
s.GenerateWallet("BTC", "", true, true);
s.GoToStore(newStore.storeId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
var paymentMethodOptions = s.Driver.FindElements(By.CssSelector("input[name='PayoutMethods']"));
Assert.Equal(2, paymentMethodOptions.Count);
@ -2344,7 +2344,7 @@ namespace BTCPayServer.Tests
//auto-approve pull payments
s.GoToStore(StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), true);
s.Driver.FindElement(By.Id("Amount")).Clear();
@ -2367,7 +2367,7 @@ namespace BTCPayServer.Tests
// LNURL Withdraw support check with BTC denomination
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), true);
s.Driver.FindElement(By.Id("Amount")).Clear();
@ -2459,7 +2459,7 @@ namespace BTCPayServer.Tests
}
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), false);
s.Driver.FindElement(By.Id("Amount")).Clear();
@ -2499,7 +2499,7 @@ namespace BTCPayServer.Tests
// LNURL Withdraw support check with SATS denomination
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
s.Driver.FindElement(By.Id("Name")).SendKeys("PP SATS");
s.Driver.SetCheckbox(By.Id("AutoApproveClaims"), true);
s.Driver.FindElement(By.Id("Amount")).Clear();
@ -3122,7 +3122,7 @@ namespace BTCPayServer.Tests
// Check that pull payment has lightning option
s.GoToStore(s.StoreId, StoreNavPages.PullPayments);
s.Driver.FindElement(By.Id("NewPullPayment")).Click();
s.ClickPagePrimary();
Assert.Equal(PaymentTypes.LN.GetPaymentMethodId(cryptoCode), PaymentMethodId.Parse(Assert.Single(s.Driver.FindElements(By.CssSelector("input[name='PayoutMethods']"))).GetAttribute("value")));
s.Driver.FindElement(By.Id("Name")).SendKeys("PP1");
s.Driver.FindElement(By.Id("Amount")).Clear();

View File

@ -15,8 +15,10 @@ using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Controllers;
using ExchangeSharp;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using NBitcoin;
@ -27,6 +29,7 @@ using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using Xunit;
using Xunit.Abstractions;
using static System.Net.Mime.MediaTypeNames;
namespace BTCPayServer.Tests
{
@ -267,6 +270,63 @@ retry:
Thread.Sleep(200);
}
class TranslatedKeyNodeWalker : IntermediateNodeWalker
{
private List<string> _defaultTranslatedKeys;
private string _txt;
public TranslatedKeyNodeWalker(List<string> defaultTranslatedKeys)
{
_defaultTranslatedKeys = defaultTranslatedKeys;
}
public TranslatedKeyNodeWalker(List<string> defaultTranslatedKeys, string txt) : this(defaultTranslatedKeys)
{
_txt = txt;
}
public override void VisitTagHelper(TagHelperIntermediateNode node)
{
if (node.TagName == "input")
{
foreach (var tagHelper in node.TagHelpers)
{
if (tagHelper.Name.EndsWith("TranslateTagHelper"))
{
var inner = ToString(node);
if (inner.Contains("type=\"submit\""))
{
var m = Regex.Match(inner, "value=\"(.*?)\"");
if (m.Success)
{
_defaultTranslatedKeys.Add(m.Groups[1].Value);
}
}
}
}
return;
}
foreach (var tagHelper in node.TagHelpers)
{
if (tagHelper.Name.EndsWith("TranslateTagHelper"))
{
var htmlContent = node.FindDescendantNodes<HtmlContentIntermediateNode>().FirstOrDefault();
if (htmlContent is not null)
{
var inner = ToString(htmlContent);
_defaultTranslatedKeys.Add(inner);
}
}
}
base.VisitTagHelper(node);
}
private string ToString(IntermediateNode? node)
{
return _txt.Substring(node.Source.Value.AbsoluteIndex, node.Source.Value.Length);
}
}
/// <summary>
/// This utilities crawl through the cs files in search for
/// Display attributes, then update Translations.Default to list them
@ -308,30 +368,17 @@ retry:
defaultTranslatedKeys.Add(match.Groups[1].Value);
}
}
else if (txt.Contains("text-translate"))
{
filePath = filePath.Replace(Path.Combine(soldir.FullName, "BTCPayServer"), "/");
var item = engine.FileSystem.GetItem(filePath);
filePath = filePath.Replace(Path.Combine(soldir.FullName, "BTCPayServer"), "/");
var item = engine.FileSystem.GetItem(filePath);
var node = (DocumentIntermediateNode)engine.Process(item).Items[typeof(DocumentIntermediateNode)];
foreach (var n in node.FindDescendantNodes<TagHelperIntermediateNode>())
{
foreach (var tagHelper in n.TagHelpers)
{
if (tagHelper.Name.EndsWith("TranslateTagHelper"))
{
var htmlContent = n.FindDescendantNodes<HtmlContentIntermediateNode>().First();
var inner = txt.Substring(htmlContent.Source.Value.AbsoluteIndex, htmlContent.Source.Value.Length);
defaultTranslatedKeys.Add(inner);
}
}
}
}
var node = (DocumentIntermediateNode)engine.Process(item).Items[typeof(DocumentIntermediateNode)];
var w = new TranslatedKeyNodeWalker(defaultTranslatedKeys, txt);
w.Visit(node);
}
}
defaultTranslatedKeys = defaultTranslatedKeys.Distinct().OrderBy(o => o).ToList();
defaultTranslatedKeys = defaultTranslatedKeys.Select(d => d.Trim()).Distinct().OrderBy(o => o).ToList();
var path = Path.Combine(soldir.FullName, "BTCPayServer/Services/Translations.Default.cs");
var defaultTranslation = File.ReadAllText(path);
var startIdx = defaultTranslation.IndexOf("\"\"\"");

View File

@ -34,43 +34,43 @@
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Dashboard))" asp-area="" asp-controller="UIStores" asp-action="Dashboard" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Dashboard)">
<vc:icon symbol="nav-dashboard"/>
<span>Dashboard</span>
<span text-translate="true">Dashboard</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.General))" asp-area="" asp-controller="UIStores" asp-action="GeneralSettings" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.General)">
<vc:icon symbol="nav-store-settings"/>
<span>Settings</span>
<span text-translate="true">Settings</span>
</a>
</li>
@if (ViewData.IsActivePage([StoreNavPages.General, StoreNavPages.Rates, StoreNavPages.CheckoutAppearance, StoreNavPages.Tokens, StoreNavPages.Users, StoreNavPages.Roles, StoreNavPages.Webhooks, StoreNavPages.PayoutProcessors, StoreNavPages.Emails, StoreNavPages.Forms]))
{
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Rates))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Rates)" asp-controller="UIStores" asp-action="Rates" asp-route-storeId="@Model.Store.Id">Rates</a>
<a id="StoreNav-@(nameof(StoreNavPages.Rates))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Rates)" asp-controller="UIStores" asp-action="Rates" asp-route-storeId="@Model.Store.Id" text-translate="true">Rates</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.CheckoutAppearance))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.CheckoutAppearance)" asp-controller="UIStores" asp-action="CheckoutAppearance" asp-route-storeId="@Model.Store.Id">Checkout Appearance</a>
<a id="StoreNav-@(nameof(StoreNavPages.CheckoutAppearance))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.CheckoutAppearance)" asp-controller="UIStores" asp-action="CheckoutAppearance" asp-route-storeId="@Model.Store.Id" text-translate="true">Checkout Appearance</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Tokens))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Tokens)" asp-controller="UIStores" asp-action="ListTokens" asp-route-storeId="@Model.Store.Id">Access Tokens</a>
<a id="StoreNav-@(nameof(StoreNavPages.Tokens))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Tokens)" asp-controller="UIStores" asp-action="ListTokens" asp-route-storeId="@Model.Store.Id" text-translate="true">Access Tokens</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Users))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Users)" asp-controller="UIStores" asp-action="StoreUsers" asp-route-storeId="@Model.Store.Id">Users</a>
<a id="StoreNav-@(nameof(StoreNavPages.Users))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Users)" asp-controller="UIStores" asp-action="StoreUsers" asp-route-storeId="@Model.Store.Id" text-translate="true">Users</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Roles))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Roles)" asp-controller="UIStores" asp-action="ListRoles" asp-route-storeId="@Model.Store.Id">Roles</a>
<a id="StoreNav-@(nameof(StoreNavPages.Roles))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Roles)" asp-controller="UIStores" asp-action="ListRoles" asp-route-storeId="@Model.Store.Id" text-translate="true">Roles</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Webhooks))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Webhooks)" asp-controller="UIStores" asp-action="Webhooks" asp-route-storeId="@Model.Store.Id">Webhooks</a>
<a id="StoreNav-@(nameof(StoreNavPages.Webhooks))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Webhooks)" asp-controller="UIStores" asp-action="Webhooks" asp-route-storeId="@Model.Store.Id" text-translate="true">Webhooks</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.PayoutProcessors))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PayoutProcessors)" asp-controller="UIPayoutProcessors" asp-action="ConfigureStorePayoutProcessors" asp-route-storeId="@Model.Store.Id">Payout Processors</a>
<a id="StoreNav-@(nameof(StoreNavPages.PayoutProcessors))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PayoutProcessors)" asp-controller="UIPayoutProcessors" asp-action="ConfigureStorePayoutProcessors" asp-route-storeId="@Model.Store.Id" text-translate="true">Payout Processors</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Emails))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Emails)" asp-controller="UIStores" asp-action="StoreEmailSettings" asp-route-storeId="@Model.Store.Id">Emails</a>
<a id="StoreNav-@(nameof(StoreNavPages.Emails))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Emails)" asp-controller="UIStores" asp-action="StoreEmailSettings" asp-route-storeId="@Model.Store.Id" text-translate="true">Emails</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyStoreSettings">
<a id="StoreNav-@(nameof(StoreNavPages.Forms))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Forms)" asp-controller="UIForms" asp-action="FormsList" asp-route-storeId="@Model.Store.Id">Forms</a>
<a id="StoreNav-@(nameof(StoreNavPages.Forms))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Forms)" asp-controller="UIForms" asp-action="FormsList" asp-route-storeId="@Model.Store.Id" text-translate="true">Forms</a>
</li>
}
<vc:ui-extension-point location="store-nav" model="@Model"/>
@ -79,9 +79,7 @@
</div>
<div class="accordion-item">
<header class="accordion-header" id="Nav-Wallets-Header" permission="@Policies.CanModifyStoreSettings">
<div class="accordion-button">
Wallets
</div>
<div text-translate="true" class="accordion-button">Wallets</div>
</header>
<div id="Nav-Wallets" class="accordion-collapse" aria-labelledby="Nav-Wallets-Header" permission="@Policies.CanModifyStoreSettings">
<div class="accordion-body">
@ -157,7 +155,7 @@
<div class="accordion-item">
<header class="accordion-header" id="Nav-Payments-Header">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#Nav-Payments" aria-expanded="true" aria-controls="Nav-Payments">
Payments
<span text-translate="true">Payments</span>
<vc:icon symbol="caret-down"/>
</button>
</header>
@ -167,25 +165,25 @@
<li class="nav-item" permission="@Policies.CanViewInvoices">
<a asp-area="" asp-controller="UIInvoice" asp-action="ListInvoices" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActiveCategoryClass(typeof(InvoiceNavPages))" id="StoreNav-Invoices">
<vc:icon symbol="nav-invoices"/>
<span>Invoices</span>
<span text-translate="true">Invoices</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewReports">
<a asp-area="" asp-controller="UIReports" asp-action="StoreReports" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Reporting)" id="SectionNav-Reporting">
<vc:icon symbol="nav-reporting" />
<span>Reporting</span>
<span text-translate="true">Reporting</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewPaymentRequests">
<a asp-area="" asp-controller="UIPaymentRequest" asp-action="GetPaymentRequests" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActiveCategoryClass(typeof(PaymentRequestsNavPages))" id="StoreNav-PaymentRequests">
<vc:icon symbol="nav-payment-requests"/>
<span>Requests</span>
<span text-translate="true">Requests</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewPullPayments">
<a asp-area="" asp-controller="UIStorePullPayments" asp-action="PullPayments" asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PullPayments)" id="StoreNav-PullPayments">
<vc:icon symbol="nav-pull-payments"/>
<span>Pull Payments</span>
<span text-translate="true">Pull Payments</span>
</a>
</li>
<li class="nav-item" permission="@Policies.CanViewPayouts">
@ -194,7 +192,7 @@
asp-route-pullPaymentId=""
asp-route-storeId="@Model.Store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.Payouts)" id="StoreNav-Payouts">
<vc:icon symbol="nav-payouts"/>
<span>Payouts</span>
<span text-translate="true">Payouts</span>
</a>
</li>
</ul>
@ -206,7 +204,7 @@
<div class="accordion-item">
<header class="accordion-header" id="Nav-Plugins-Header">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#Nav-Plugins" aria-expanded="true" aria-controls="Nav-Plugins">
Plugins
<span text-translate="true">Plugins</span>
<vc:icon symbol="caret-down"/>
</button>
</header>
@ -230,7 +228,7 @@
{
<vc:icon symbol="nav-plugins-manage" />
}
<span>Manage Plugins</span>
<span text-translate="true">Manage Plugins</span>
</a>
</li>
@if (Model.Store != null && Model.ArchivedAppsCount > 0)
@ -274,11 +272,11 @@
@if (!PoliciesSettings.LockSubscription)
{
<li class="nav-item">
<a asp-area="" asp-controller="UIAccount" asp-action="Register" class="nav-link" id="Nav-Register">Register</a>
<a asp-area="" asp-controller="UIAccount" asp-action="Register" class="nav-link" id="Nav-Register" text-translate="true">Register</a>
</li>
}
<li class="nav-item">
<a asp-area="" asp-controller="UIAccount" asp-action="Login" class="nav-link" id="Nav-Login">Log in</a>
<a asp-area="" asp-controller="UIAccount" asp-action="Login" class="nav-link" id="Nav-Login" text-translate="true">Log in</a>
</li>
</ul>
}
@ -289,47 +287,47 @@
<li class="nav-item" permission="@Policies.CanModifyServerSettings">
<a asp-area="" asp-controller="UIServer" asp-action="Policies" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Policies)" id="Nav-ServerSettings">
<vc:icon symbol="nav-server-settings"/>
<span>Server Settings</span>
<span text-translate="true">Server Settings</span>
</a>
</li>
@if (ViewData.IsActiveCategory(typeof(ServerNavPages)) && !ViewData.IsActivePage([ServerNavPages.Plugins]))
{
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Users" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Users)" asp-action="ListUsers">Users</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Users" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Users)" asp-action="ListUsers" text-translate="true">Users</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Roles" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Roles)" asp-action="ListRoles">Roles</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Roles" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Roles)" asp-action="ListRoles" text-translate="true">Roles</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Emails" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Emails)" asp-action="Emails">Email</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Emails" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Emails)" asp-action="Emails" text-translate="true">Email</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Services" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Services)" asp-action="Services">Services</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Services" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Services)" asp-action="Services" text-translate="true">Services</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Branding" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Branding)" asp-action="Branding">Branding</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Branding" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Branding)" asp-action="Branding" text-translate="true">Branding</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Translations" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Translations)" asp-action="ListDictionaries">Translations</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Translations" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Translations)" asp-action="ListDictionaries" text-translate="true">Translations</a>
</li>
@if (BtcPayServerOptions.DockerDeployment)
{
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Maintenance" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Maintenance)" asp-action="Maintenance">Maintenance</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Maintenance" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Maintenance)" asp-action="Maintenance" text-translate="true">Maintenance</a>
</li>
}
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Logs" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Logs)" asp-action="LogsView">Logs</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Logs" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Logs)" asp-action="LogsView" text-translate="true">Logs</a>
</li>
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Files" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Files)" asp-action="Files">Files</a>
<a asp-controller="UIServer" id="SectionNav-@ServerNavPages.Files" class="nav-link @ViewData.ActivePageClass(ServerNavPages.Files)" asp-action="Files" text-translate="true">Files</a>
</li>
}
<vc:ui-extension-point location="server-nav" model="@Model"/>
<li class="nav-item dropup">
<a class="nav-link @ViewData.ActivePageClass(ManageNavPages.Index)" role="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" id="Nav-Account">
<vc:icon symbol="nav-account"/>
<span>Account</span>
<span text-translate="true">Account</span>
</a>
<ul class="dropdown-menu py-0 w-100" aria-labelledby="Nav-Account">
<li class="p-3 border-bottom d-flex align-items-center gap-2">
@ -350,7 +348,7 @@
</strong>
@if (User.IsInRole(Roles.ServerAdmin))
{
<div class="text-secondary">Administrator</div>
<div class="text-secondary" text-translate="true">Administrator</div>
}
</div>
</li>
@ -362,7 +360,7 @@
}
<li class="py-1 px-3">
<label class="d-flex align-items-center justify-content-between gap-3 nav-link">
<span class="fw-semibold">Hide Sensitive Info</span>
<span class="fw-semibold" text-translate="true">Hide Sensitive Info</span>
<input id="HideSensitiveInfo" name="HideSensitiveInfo" type="checkbox" class="btcpay-toggle" />
</label>
<script>
@ -371,12 +369,12 @@
</li>
<li class="border-top py-1 px-3">
<a asp-area="" asp-controller="UIManage" asp-action="Index" class="nav-link" id="Nav-ManageAccount">
<span>Manage Account</span>
<span text-translate="true">Manage Account</span>
</a>
</li>
<li class="border-top py-1 px-3">
<a asp-area="" asp-controller="UIAccount" asp-action="Logout" class="nav-link text-danger" id="Nav-Logout">
<span>Logout</span>
<span text-translate="true">Logout</span>
</a>
</li>
</ul>
@ -384,19 +382,19 @@
@if (ViewData.IsActiveCategory(typeof(ManageNavPages)) || ViewData.IsActivePage([ManageNavPages.ChangePassword]))
{
<li class="nav-item nav-item-sub">
<a id="SectionNav-@ManageNavPages.ChangePassword.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.ChangePassword)" asp-controller="UIManage" asp-action="ChangePassword">Password</a>
<a id="SectionNav-@ManageNavPages.ChangePassword.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.ChangePassword)" asp-controller="UIManage" asp-action="ChangePassword" text-translate="true">Password</a>
</li>
<li class="nav-item nav-item-sub">
<a id="SectionNav-@ManageNavPages.TwoFactorAuthentication.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.TwoFactorAuthentication)" asp-controller="UIManage" asp-action="TwoFactorAuthentication">Two-Factor Authentication</a>
<a id="SectionNav-@ManageNavPages.TwoFactorAuthentication.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.TwoFactorAuthentication)" asp-controller="UIManage" asp-action="TwoFactorAuthentication" text-translate="true">Two-Factor Authentication</a>
</li>
<li class="nav-item nav-item-sub">
<a id="SectionNav-@ManageNavPages.APIKeys.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.APIKeys)" asp-controller="UIManage" asp-action="APIKeys">API Keys</a>
<a id="SectionNav-@ManageNavPages.APIKeys.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.APIKeys)" asp-controller="UIManage" asp-action="APIKeys" text-translate="true">API Keys</a>
</li>
<li class="nav-item nav-item-sub">
<a id="SectionNav-@ManageNavPages.Notifications.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.Notifications)" asp-controller="UIManage" asp-action="NotificationSettings">Notifications</a>
<a id="SectionNav-@ManageNavPages.Notifications.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.Notifications)" asp-controller="UIManage" asp-action="NotificationSettings" text-translate="true">Notifications</a>
</li>
<li class="nav-item nav-item-sub">
<a id="SectionNav-@ManageNavPages.LoginCodes.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.LoginCodes)" asp-controller="UIManage" asp-action="LoginCodes">Login Codes</a>
<a id="SectionNav-@ManageNavPages.LoginCodes.ToString()" class="nav-link @ViewData.ActivePageClass(ManageNavPages.LoginCodes)" asp-controller="UIManage" asp-action="LoginCodes" text-translate="true">Login Codes</a>
</li>
<vc:ui-extension-point location="user-nav" model="@Model" />
}
@ -405,7 +403,7 @@
<li class="nav-item">
<a href="@Model.ContactUrl" class="nav-link" id="Nav-ContactUs">
<vc:icon symbol="nav-contact"/>
<span>Contact Us</span>
<span text-translate="true">Contact Us</span>
</a>
</li>
}

View File

@ -1,7 +1,7 @@
@model BTCPayServer.Components.ThemeSwitch.ThemeSwitchViewModel
<div class="btcpay-theme-switch @Model.CssClass">
<span class="btcpay-theme-switch-label">Theme</span>
<span class="btcpay-theme-switch-label" text-translate="true">Theme</span>
<div class="btcpay-theme-switch-themes">
<button type="button" title="System" data-theme="system"><vc:icon symbol="themes-system"/></button>
<button type="button" title="Light" data-theme="light"><vc:icon symbol="themes-light"/></button>

View File

@ -7,6 +7,7 @@ using BTCPayServer.Models.ServerViewModels;
using BTCPayServer.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Controllers
{
@ -78,6 +79,18 @@ namespace BTCPayServer.Controllers
var d = await this._localizer.GetDictionary(dictionary);
if (d is null)
return NotFound();
if (Environment.CheatMode && viewModel.Command == "Fake")
{
var t = await _localizer.GetTranslations(dictionary);
var jobj = JObject.Parse(t.Translations.ToJsonFormat());
foreach (var prop in jobj.Properties())
{
prop.Value = "OK";
}
viewModel.Translations = Translations.CreateFromJson(jobj.ToString()).ToTextFormat();
}
if (!Translations.TryCreateFromText(viewModel.Translations, out var translations))
{
ModelState.AddModelError(nameof(viewModel.Translations), "Syntax error");

View File

@ -95,7 +95,8 @@ namespace BTCPayServer.Controllers
IHostApplicationLifetime applicationLifetime,
IHtmlHelper html,
TransactionLinkProviders transactionLinkProviders,
LocalizerService localizer
LocalizerService localizer,
BTCPayServerEnvironment environment
)
{
_policiesSettings = policiesSettings;
@ -123,6 +124,7 @@ namespace BTCPayServer.Controllers
Html = html;
_transactionLinkProviders = transactionLinkProviders;
_localizer = localizer;
Environment = environment;
}
[HttpGet("server/stores")]
@ -325,6 +327,7 @@ namespace BTCPayServer.Controllers
public IHttpClientFactory HttpClientFactory { get; }
public IHostApplicationLifetime ApplicationLifetime { get; }
public IHtmlHelper Html { get; }
public BTCPayServerEnvironment Environment { get; }
[Route("server/policies")]
public async Task<IActionResult> Policies()

View File

@ -6,6 +6,7 @@ public class EditDictionaryViewModel
{
public string Translations { get; set; }
public int Lines { get; set; }
public string Command { get; set; }
internal EditDictionaryViewModel SetTranslations(Translations translations)
{

View File

@ -11,13 +11,22 @@ namespace BTCPayServer.Services
// Please run it before release.
var knownTranslations =
"""
Access Tokens
Account
Account key
Account key path
Add additional fee (network fee) to invoice
Add Address
Add Exchange Rate Spread
Add hop hints for private channels to the Lightning invoice
Add Role
Add Service
Add User
Add Webhook
Additional Actions
Admin API access token
Admin must approve new users
Administrator
Allow anyone to create invoice
Allow form for public use
Allow payee to create invoices with custom amounts
@ -27,10 +36,13 @@ Always include non-witness UTXO if available
Amazon S3
Amount
API Key
API Keys
App
App Name
App Type
Application
Approve
Archive this store
Authenticator code
Auto-detect language on checkout
Automatically approve claims
@ -40,12 +52,14 @@ Backend's language
Batch size
BIP39 Seed (12/24 word mnemonic phrase) or HD private key (xprv...)
Brand Color
Branding
Buyer Email
Callback Notification URL
Can use hot wallet
Can use RPC import
Celebrate payment with confetti
Check releases on GitHub and notify when new BTCPay Server version is available
Checkout Appearance
Colors to rotate between with animation when a payment is made. One color per line.
Confirm new password
Confirm password
@ -53,8 +67,20 @@ Connection string
Consider the invoice paid even if the paid amount is % less than expected
Consider the invoice settled when the payment transaction
Contact URL
Contact Us
Contribution Perks Template
Count all invoices created on the store as part of the goal
Create
Create a new app
Create Account
Create Form
Create Invoice
Create Pull Payment
Create Request
Create Store
Create Webhook
Create your account
Crowdfund
Currency
Current password
Custom CSS
@ -62,10 +88,12 @@ Custom HTML title to display on Checkout page
Custom sound file for successful payment
Custom Theme Extension Type
Custom Theme File
Dashboard
Default currency
Default language on checkout
Default payment method on checkout
Default role for users on a new store
Delete this store
Derivation scheme
Derivation scheme format
Description
@ -92,6 +120,7 @@ Email
Email address
Email confirmation required
Email confirmed?
Emails
Enable background animations on new payments
Enable Disqus Comments
Enable experimental features
@ -105,18 +134,27 @@ Enable tips
End date
Error
Expiration Date
Export
Extends the BTCPay Server Dark theme
Extends the BTCPay Server Light theme
Featured Image URL
Fee rate (sat/vB)
Files
Forgot password?
Form configuration (JSON)
Forms
Gap limit
Generate
Generate API Key
Generate Key
Google Cloud Storage
GRPC SSL Cipher suite (GRPC_SSL_CIPHER_SUITES)
Hide Sensitive Info
Image
Invoice currency
Invoice expires if the full amount has not been paid after
Invoice metadata
Invoices
Is administrator?
Is signing key
Item Description
@ -124,8 +162,15 @@ Keypad
Lightning node (LNURL Auth)
LNURL Classic Mode
Local File System
Log in
Login Codes
Logo
Logout
Logs
Maintenance
Make Crowdfund Public
Manage Account
Manage Plugins
Master fingerprint
Max sats
Memo
@ -133,6 +178,7 @@ Metadata
Min sats
Minimum acceptable expiration time for BOLT11 for refunds
New password
Next
Non-admins can access the User Creation API Endpoint
Non-admins can create Hot Wallets for their Store
Non-admins can import Hot Wallets for their Store
@ -140,6 +186,7 @@ Non-admins can use the Internal Lightning Node for their Store
Non-admins cannot access the User Creation API Endpoint
Notification Email
Notification URL
Notifications
Only enable the payment method after user explicitly chooses it
Optional seed passphrase
Order Id
@ -147,10 +194,17 @@ Override the block explorers used
Pair to
Password
Password (leave blank to generate invite-link)
Pay Button
PayJoin BIP21
Payment
Payment invalid if transactions fails to confirm after invoice expiration
Payments
Payout Methods
Payout Processors
Payouts
Plugin server
Plugins
Point of Sale
Point of Sale Style
Policies
Preferred Price Source
@ -161,26 +215,41 @@ Profile Picture
PSBT content
PSBT to combine with
Public Key
Pull Payments
Rate Rules
Rates
Recommended fee confirmation target blocks
Recovery Code
Redirect invoice to redirect url automatically after paid
Redirect URL
Regenerate code
Register
Remember me
Remember this machine
Reporting
Request contributor data on checkout
Request customer data on checkout
Request Pairing
Requests
Reset goal every
REST Uri
Role
Roles
Root fingerprint
Save
Scope
Search engines can index this site
Security device (FIDO2)
Select the Default Currency during Store Creation
Select the payout method used for refund
Send test webhook
Server Name
Server Settings
Services
Set Password
Settings
Shop Name
Shopify
Show "Pay in wallet" button
Show a timer minutes before invoice expiration
Show plugins in pre-release
@ -197,7 +266,9 @@ Starting index
Store
Store Id
Store Name
Store Settings
Store Website
Submit
Subtract fees from amount
Support URL
Supported Transaction Currencies
@ -206,18 +277,27 @@ Test Email
Text to display in the tip input
Text to display on buttons allowing the user to enter a custom amount
Text to display on each button for items with a specific price
Theme
Tip percentage amounts (comma separated)
Translations
Two-Factor Authentication
Unarchive this store
Unify on-chain and lightning payment URL/QR code
Update Password
Update Webhook
Upload PSBT from file
Url of the Dynamic DNS service you are using
Use custom theme
Use SSL
User can input custom amount
User can input discount in %
Users
UTXOs to spend from
Verification Code
Wallet file
Wallet file content
Wallets
Webhooks
Welcome to {0}
Your dynamic DNS hostname
""";

View File

@ -10,6 +10,9 @@ using BTCPayServer.Data;
using Microsoft.EntityFrameworkCore;
using System;
using System.Runtime.InteropServices;
using Newtonsoft.Json.Linq;
using static System.Net.Mime.MediaTypeNames;
using YamlDotNet.Core.Tokens;
namespace BTCPayServer.Services
{
@ -34,6 +37,22 @@ namespace BTCPayServer.Services
return false;
}
}
public static Translations CreateFromJson(string text)
{
text = (text ?? "{}");
var translations = new List<(string key, string? value)>();
foreach (var prop in JObject.Parse(text).Properties())
{
var v = prop.Value.Value<string>();
if (string.IsNullOrEmpty(v))
translations.Add((prop.Name, prop.Name));
else
translations.Add((prop.Name, v));
}
return new Translations(translations
.Select(t => KeyValuePair.Create(t.key, t.value)));
}
public static Translations CreateFromText(string text)
{
text = (text ?? "").Replace("\r\n", "\n");
@ -116,7 +135,15 @@ namespace BTCPayServer.Services
{
return GetEnumerator();
}
public string ToJsonFormat()
{
JObject obj = new JObject();
foreach (var record in Records)
{
obj.Add(record.Key, record.Value);
}
return obj.ToString(Newtonsoft.Json.Formatting.Indented);
}
public string ToTextFormat()
{
return string.Join('\n', Records.OrderBy(r => r.Key).Select(r => $"{r.Key} => {r.Value}").ToArray());

View File

@ -1,9 +1,11 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using AngleSharp.Html;
using BTCPayServer.Abstractions.Services;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
@ -12,6 +14,8 @@ namespace BTCPayServer.TagHelpers
{
[HtmlTargetElement(Attributes = "text-translate")]
[HtmlTargetElement(Attributes = "html-translate")]
[HtmlTargetElement("input", Attributes = "[type=submit]")]
[HtmlTargetElement(Attributes = "[id=page-primary]")]
public class TranslateTagHelper : TagHelper
{
private readonly IStringLocalizer<TranslateTagHelper> _localizer;
@ -19,6 +23,7 @@ namespace BTCPayServer.TagHelpers
public bool TextTranslate { get; set; }
public bool HtmlTranslate { get; set; }
public string Value { get; set; }
public TranslateTagHelper(
@ -41,15 +46,26 @@ namespace BTCPayServer.TagHelpers
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var originalContent = output.Content.IsModified
? output.Content.GetContent()
: (await output.GetChildContentAsync()).GetContent();
var newContent = _localizer[originalContent];
if (TextTranslate)
output.Content.SetContent(newContent);
if (Value != null)
{
output.CopyHtmlAttribute("value", context);
}
if (context.TagName == "input")
{
var newContent = _localizer[Value];
output.Attributes.SetAttribute("value", newContent.Value);
}
else
output.Content.SetHtmlContent(_safe.Raw(newContent.Value));
{
var originalContent = output.Content.IsModified
? output.Content.GetContent()
: (await output.GetChildContentAsync()).GetContent();
var newContent = _localizer[originalContent.Trim()];
if (HtmlTranslate)
output.Content.SetHtmlContent(_safe.Raw(newContent.Value));
else
output.Content.SetContent(newContent);
}
}
}
}

View File

@ -30,7 +30,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>

View File

@ -16,7 +16,7 @@
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<a asp-area="" asp-controller="UIApps" asp-action="CreateApp" asp-route-storeId="@store.Id" asp-route-appType="@appType.Type" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Create, appType.Type)" id="@($"StoreNav-Create{appType.Type}")">
<vc:icon symbol="nav-crowdfund" />
<span>@appType.Description</span>
<span text-translate="true">Crowdfund</span>
</a>
</li>
@if (apps.Any())
@ -24,7 +24,7 @@
<li class="nav-item" not-permission="@Policies.CanModifyStoreSettings" permission="@Policies.CanViewStoreSettings">
<span class="nav-link">
<vc:icon symbol="nav-crowdfund" />
<span>@appType.Description</span>
<span>Crowdfund</span>
</span>
</li>
}

View File

@ -27,7 +27,7 @@
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<div>
<button id="page-primary" type="submit" class="btn btn-primary order-sm-1">Save</button>
@if (Model.Archived)

View File

@ -25,7 +25,7 @@
}
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<a id="page-primary" class="btn btn-primary" role="button" asp-controller="@controller" asp-action="CreateOrEditRole" asp-route-role="create" asp-route-storeId="@storeId" permission="@permission">Add Role</a>
</div>
<partial name="_StatusMessage" />

View File

@ -4,7 +4,7 @@
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />

View File

@ -8,7 +8,7 @@
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<a asp-area="" asp-controller="UIPayButton" asp-action="PayButton" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass(StoreNavPages.PayButton)" id="StoreNav-PayButton">
<vc:icon symbol="nav-pay-button"/>
<span>Pay Button</span>
<span text-translate="true">Pay Button</span>
</a>
</li>
}

View File

@ -175,7 +175,7 @@
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />

View File

@ -16,7 +16,7 @@
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<a asp-area="" asp-controller="UIApps" asp-action="CreateApp" asp-route-storeId="@store.Id" asp-route-appType="@appType.Type" class="nav-link @ViewData.ActivePageClass(AppsNavPages.Create, appType.Type)" id="@($"StoreNav-Create{appType.Type}")">
<vc:icon symbol="nav-pointofsale" />
<span>@appType.Description</span>
<span text-translate="true">Point of Sale</span>
</a>
</li>
@if (apps.Any())
@ -24,7 +24,7 @@
<li class="nav-item" not-permission="@Policies.CanModifyStoreSettings" permission="@Policies.CanViewStoreSettings">
<span class="nav-link">
<vc:icon symbol="nav-pointofsale" />
<span>@appType.Description</span>
<span>Point of Sale</span>
</span>
</li>
}

View File

@ -35,7 +35,7 @@
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<div>
<button id="page-primary" type="submit" class="btn btn-primary order-sm-1">Save</button>
@if (Model.Archived)

View File

@ -10,7 +10,7 @@
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
<a asp-area="" asp-controller="UIShopify" asp-action="EditShopify" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass("shopify", nameof(StoreNavPages))" id="StoreNav-Shopify">
<vc:icon symbol="logo-shopify" />
<span>Shopify</span>
<span text-translate="true">Shopify</span>
</a>
</li>
}

View File

@ -8,4 +8,4 @@
}
}
<partial name="_Form" model="@Model.Form" />
<input id="page-primary" type="submit" class="btn btn-primary" name="command" value="Submit" />
<input id="page-primary" type="submit" class="btn btn-primary" value="Submit" />

View File

@ -2,7 +2,7 @@
ViewData["Title"] = "Signed out";
}
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<p>
You have successfully signed out.
</p>

View File

@ -9,7 +9,7 @@
<form asp-action="CreateApp" asp-route-appType="@Model.AppType">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<input id="page-primary" type="submit" value="Create" class="btn btn-primary" />
</div>
<partial name="_StatusMessage" />

View File

@ -11,7 +11,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">Register Device</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -36,7 +36,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<input id="page-primary" type="submit" value="Create" class="btn btn-primary" />
</div>

View File

@ -177,7 +177,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">Invoice</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<div>
@if (Model.ShowCheckout)

View File

@ -26,7 +26,7 @@
}
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<a id="page-primary" data-bs-toggle="collapse" data-bs-target="#AddAddress" class="btn btn-primary" role="button">
Add Address
</a>

View File

@ -9,7 +9,7 @@
};
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<p>Scan the QR code with your Lightning wallet to link it to your user account.</p>

View File

@ -16,7 +16,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" name="command" type="submit" class="btn btn-primary" value="Save">Save</button>
</div>

View File

@ -5,7 +5,7 @@
var cryptoCode = Context.GetRouteValue("cryptoCode");
}
<h2 class="mt-1 mb-2">@ViewData["Title"]</h2>
<h2 class="mt-1 mb-2" text-translate="true">@ViewData["Title"]</h2>
<div class="row">
<div class="col-md-12">
<ul class="list-group list-group-flush">

View File

@ -5,7 +5,7 @@
ViewData["Title"] = "Lightning Payout Result";
}
<h2 class="mt-1 mb-4">@ViewData["Title"]</h2>
<h2 class="mt-1 mb-4" text-translate="true">@ViewData["Title"]</h2>
@foreach (var item in Model)
{
<div class="alert alert-@(item.Result == PayResult.Ok ? "success" : "danger") mb-3" role="alert">

View File

@ -8,7 +8,7 @@
}
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<a id="page-primary" class="btn btn-primary" asp-action="AddApiKey">
Generate Key
</a>

View File

@ -34,7 +34,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" type="submit" class="btn btn-primary">Generate API Key</button>
</div>

View File

@ -5,7 +5,7 @@
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary">Update Password</button>
</div>
<partial name="_StatusMessage" />

View File

@ -10,7 +10,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -1,9 +1,9 @@
@model GenerateRecoveryCodesViewModel
@model GenerateRecoveryCodesViewModel
@{
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Recovery codes");
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<div class="alert alert-warning" role="alert">

View File

@ -10,7 +10,7 @@
<form method="post" enctype="multipart/form-data">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary">Save</button>
</div>
<partial name="_StatusMessage" />

View File

@ -4,7 +4,7 @@
}
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<a id="page-primary" class="btn btn-primary" asp-action="LoginCodes">Regenerate code</a>
</div>
<partial name="_StatusMessage" />

View File

@ -12,7 +12,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="update">Save</button>
</div>

View File

@ -5,7 +5,7 @@
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary">Set Password</button>
</div>
<partial name="_StatusMessage" />

View File

@ -4,7 +4,7 @@
ViewData.SetActivePage(ManageNavPages.TwoFactorAuthentication, "Two-Factor Authentication");
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />
<div class="row">

View File

@ -32,7 +32,7 @@
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
<a id="NotificationSettings" asp-controller="UIManage" asp-action="NotificationSettings" class="btn btn-secondary d-flex align-items-center">
<vc:icon symbol="nav-store-settings" />
</a>

View File

@ -17,7 +17,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" name="command" type="submit" class="btn btn-primary" value="Save">Save</button>
</div>

View File

@ -30,7 +30,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<div>
@if (string.IsNullOrEmpty(Model.Id))

View File

@ -8,7 +8,7 @@
ViewData.SetActivePage(StoreNavPages.PayoutProcessors, "Payout Processors", storeId);
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<p>Payout Processors allow BTCPay Server to handle payouts in an automated way.</p>

View File

@ -23,7 +23,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<div>
@if (string.IsNullOrEmpty(Model.Id))

View File

@ -15,7 +15,7 @@
<form method="post" enctype="multipart/form-data">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<partial name="_StatusMessage" />
@ -64,8 +64,8 @@
<div class="form-text">In order to upload a logo, a <a asp-controller="UIServer" asp-action="Files">file storage</a> must be configured.</div>
}
</div>
<h3 class="mt-5 mb-3">Theme</h3>
<h3 class="mt-5 mb-3" text-translate="true">Theme</h3>
<p>Use the default Light or Dark Themes, or provide a custom CSS theme file below.</p>
<div class="d-flex align-items-center mb-3">

View File

@ -11,7 +11,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -12,7 +12,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -14,7 +14,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<input id="page-primary" type="submit" value="Create" class="btn btn-primary" />
</div>

View File

@ -6,7 +6,7 @@
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Generate">Generate</button>
</div>
<partial name="_StatusMessage" />

View File

@ -12,7 +12,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Create Account</button>
</div>

View File

@ -14,7 +14,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -14,7 +14,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -14,9 +14,12 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
<div>
<button cheat-mode="true" class="btn btn-outline-info" name="command" value="Fake">Fill fake</button>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
</div>
<partial name="_StatusMessage" />

View File

@ -14,7 +14,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -14,7 +14,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">Provider</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -5,7 +5,7 @@
<form method="post" autocomplete="off">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<partial name="_StatusMessage" />

View File

@ -4,7 +4,7 @@
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
<a asp-action="storage" asp-route-forceChoice="true" asp-route-returnurl="@ViewData["ReturnUrl"]" class="btn btn-secondary d-flex align-items-center">
<vc:icon symbol="settings" />
</a>

View File

@ -11,7 +11,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -11,7 +11,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -6,7 +6,7 @@
}
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<a id="page-primary" asp-action="CreateDictionary" class="btn btn-primary" role="button">
Create
</a>

View File

@ -1,10 +1,10 @@
@model BTCPayServer.Models.StoreViewModels.ListStoresViewModel
@model BTCPayServer.Models.StoreViewModels.ListStoresViewModel
@{
Layout = "_Layout";
ViewData.SetActivePage(ServerNavPages.Stores, "Store Overview");
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />

View File

@ -14,7 +14,7 @@
const string sortByAsc = "Sort by email ascending...";
}
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<a id="page-primary" asp-action="CreateUser" class="btn btn-primary" role="button">
Add User
</a>

View File

@ -12,7 +12,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -11,7 +11,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -1,10 +1,10 @@
@model BTCPayServer.Models.ServerViewModels.LogsViewModel
@model BTCPayServer.Models.ServerViewModels.LogsViewModel
@{
ViewData.SetActivePage(ServerNavPages.Logs, "Logs");
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />

View File

@ -1,10 +1,10 @@
@model BTCPayServer.Models.ServerViewModels.MaintenanceViewModel
@model BTCPayServer.Models.ServerViewModels.MaintenanceViewModel
@{
ViewData.SetActivePage(ServerNavPages.Maintenance, "Maintenance");
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />

View File

@ -11,7 +11,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -20,7 +20,7 @@
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<partial name="_StatusMessage" />

View File

@ -11,7 +11,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -12,7 +12,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
</div>
<partial name="_StatusMessage" />

View File

@ -1,10 +1,10 @@
@model BTCPayServer.Models.ServerViewModels.ServicesViewModel
@model BTCPayServer.Models.ServerViewModels.ServicesViewModel
@{
ViewData.SetActivePage(ServerNavPages.Services, "Services");
}
<div class="sticky-header">
<h2 class="my-1">@ViewData["Title"]</h2>
<h2 class="my-1" text-translate="true">@ViewData["Title"]</h2>
</div>
<partial name="_StatusMessage" />

View File

@ -12,7 +12,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Next</button>
</div>

View File

@ -16,7 +16,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">User</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<button id="page-primary" name="command" type="submit" class="btn btn-primary" value="Save">Save</button>
</div>

View File

@ -24,7 +24,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<input id="page-primary" type="submit" value="Create" class="btn btn-primary"/>
</div>

View File

@ -34,7 +34,7 @@
<vc:icon symbol="info" />
</a>
</h2>
<a permission="@Policies.CanCreateNonApprovedPullPayments" asp-action="NewPullPayment" asp-route-storeId="@storeId" class="btn btn-primary" role="button" id="NewPullPayment">
<a id="page-primary" permission="@Policies.CanCreateNonApprovedPullPayments" asp-action="NewPullPayment" asp-route-storeId="@storeId" class="btn btn-primary" role="button">
Create Pull Payment
</a>
</div>

View File

@ -59,7 +59,7 @@
<form method="post" enctype="multipart/form-data" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary">Save</button>
</div>
<partial name="_StatusMessage" />

View File

@ -17,12 +17,12 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
}
else
{
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
}
<input id="page-primary" type="submit" value="Request Pairing" class="btn btn-primary" />
</div>

View File

@ -14,7 +14,7 @@
var store = ViewContext.HttpContext.GetStoreData();
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
@if (Model.IsSetUp)

View File

@ -11,7 +11,7 @@
}
<form method="post" enctype="multipart/form-data" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header">
<h2>Store Settings</h2>
<h2 text-translate="true">Store Settings</h2>
<button id="page-primary" type="submit" class="btn btn-primary">Save</button>
</div>
@ -38,7 +38,7 @@
<span asp-validation-for="StoreWebsite" class="text-danger"></span>
</div>
<h3 class="mt-5 mb-3">Branding</h3>
<h3 class="mt-5 mb-3" text-translate="true">Branding</h3>
<div class="form-group">
<label asp-for="BrandColor" class="form-label"></label>
<div class="input-group">
@ -104,8 +104,8 @@
<div class="form-text">In order to upload a CSS file, a <a asp-controller="UIServer" asp-action="Files">file storage</a> must be configured.</div>
}
</div>
<h3 class="mt-5 mb-3">Payment</h3>
<h3 class="mt-5 mb-3" text-translate="true">Payment</h3>
<div class="form-group">
<label asp-for="DefaultCurrency" class="form-label"></label>
<input asp-for="DefaultCurrency" class="form-control w-auto" currency-selection />
@ -167,21 +167,21 @@
</form>
<div permission="@Policies.CanModifyStoreSettings">
<h3 class="mt-5 mb-3">Additional Actions</h3>
<h3 class="mt-5 mb-3" text-translate="true">Additional Actions</h3>
<div id="danger-zone" class="d-flex flex-wrap align-items-center gap-3 mb-5 mt-2">
<form asp-action="ToggleArchive" asp-route-storeId="@Model.Id" method="post">
<button type="submit" class="btn btn-outline-secondary" id="btn-archive-toggle">
@if (Model.Archived)
{
<span class="text-nowrap" data-bs-toggle="tooltip" title="Unarchive this store">Unarchive this store</span>
<span class="text-nowrap" data-bs-toggle="tooltip" title="Unarchive this store" text-translate="true">Unarchive this store</span>
}
else
{
<span class="text-nowrap" data-bs-toggle="tooltip" title="Archive this store so that it does not appear in the stores list by default">Archive this store</span>
<span class="text-nowrap" data-bs-toggle="tooltip" title="Archive this store so that it does not appear in the stores list by default" text-translate="true">Archive this store</span>
}
</button>
</form>
<a id="DeleteStore" class="btn btn-outline-danger" asp-action="DeleteStore" asp-route-storeId="@Model.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The store <strong>@Html.Encode(Model.StoreName)</strong> will be permanently deleted. This action will also delete all invoices, apps and data associated with the store." data-confirm-input="DELETE">Delete this store</a>
<a id="DeleteStore" class="btn btn-outline-danger" asp-action="DeleteStore" asp-route-storeId="@Model.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The store <strong>@Html.Encode(Model.StoreName)</strong> will be permanently deleted. This action will also delete all invoices, apps and data associated with the store." data-confirm-input="DELETE" text-translate="true">Delete this store</a>
</div>
</div>

View File

@ -7,7 +7,7 @@
ViewData.SetActivePage(StoreNavPages.Lightning, $"{Model.CryptoCode} Lightning", $"{Context.GetStoreData().Id}-{Model.CryptoCode}");
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<div class="mb-5">
<div class="mb-3">

View File

@ -8,7 +8,7 @@
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" name="command" type="submit" value="save" class="btn btn-primary">Save</button>
</div>
<partial name="_StatusMessage" />

View File

@ -22,7 +22,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
@if (Model.IsNew)
{

View File

@ -9,7 +9,7 @@
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" name="command" type="submit" class="btn btn-primary" value="Save">Save</button>
</div>
<partial name="_StatusMessage" />

View File

@ -30,12 +30,12 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
}
else
{
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
}
<button id="page-primary" type="submit" class="btn btn-primary mt-3" title="Approve this pairing demand">Approve</button>
</div>

View File

@ -23,7 +23,7 @@
</li>
<li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
</ol>
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
</nav>
<div permission="@Policies.CanModifyStoreSettings">
@if (Model.Rules.Any())

View File

@ -19,7 +19,7 @@
}
</style>
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xxl-constrain col-xl-8">

View File

@ -6,7 +6,7 @@
}
<form method="post">
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<button id="page-primary" type="submit" class="btn btn-primary mt-3">Send test webhook</button>
</div>
<partial name="_StatusMessage" />

View File

@ -16,7 +16,7 @@
<script src="~/vendor/vue-qrcode-reader/VueQrcodeReader.umd.min.js" asp-append-version="true"></script>
<link href="~/vendor/vue-qrcode-reader/vue-qrcode-reader.css" rel="stylesheet" asp-append-version="true"/>
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">

View File

@ -8,7 +8,7 @@
<div class="sticky-header">
<h2>@ViewData["Title"]</h2>
<h2 text-translate="true">@ViewData["Title"]</h2>
<a id="page-primary" asp-action="NewWebhook" class="btn btn-primary" role="button" asp-route-storeId="@Context.GetRouteValue("storeId")" permission="@Policies.CanModifyStoreSettings">
Create Webhook
</a>

View File

@ -52,7 +52,7 @@
}
else
{
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
<div class="row">
<div class="col-xl-8 col-xxl-constrain">

View File

@ -1,10 +1,10 @@
@using BTCPayServer.Client
@using BTCPayServer.Client
@model BTCPayServer.Models.StoreViewModels.ListStoresViewModel
@{
ViewData.SetActivePage(StoreNavPages.Index, Model.Archived ? "Archived Stores" : "Stores");
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
@if (Model.Stores.Any())
{

View File

@ -22,6 +22,6 @@
<span asp-validation-for="PreferredExchange" class="text-danger"></span>
</div>
<div class="form-group mt-4">
<input type="submit" value="Create Store" class="btn btn-primary" id="Create" />
<input type="submit" value="Create Store" class="btn btn-primary" id="Create" />
</div>
</form>

View File

@ -1,4 +1,4 @@
@using BTCPayServer.Abstractions.Models
@using BTCPayServer.Abstractions.Models
@model WalletLabelsModel
@{
var walletId = Context.GetRouteValue("walletId").ToString();
@ -11,7 +11,7 @@
</script>
}
<h2 class="mb-2 mb-lg-3">@ViewData["Title"]</h2>
<h2 class="mb-2 mb-lg-3" text-translate="true">@ViewData["Title"]</h2>
<partial name="_StatusMessage" />
@if (Model.Labels.Any())