mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 01:43:50 +01:00
Add translations to the Dashboard
This commit is contained in:
parent
73a9835a27
commit
c35af2dc69
@ -8,6 +8,14 @@ namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class SetStatusMessageModelExtensions
|
||||
{
|
||||
public static void SetStatusSuccess(this ITempDataDictionary tempData, string statusMessage)
|
||||
{
|
||||
tempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Success,
|
||||
Message = statusMessage
|
||||
});
|
||||
}
|
||||
public static void SetStatusMessageModel(this ITempDataDictionary tempData, StatusMessageModel statusMessage)
|
||||
{
|
||||
if (statusMessage == null)
|
||||
|
@ -16,11 +16,13 @@ using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Controllers;
|
||||
using ExchangeSharp;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
using Microsoft.AspNetCore.Mvc.Localization;
|
||||
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 Microsoft.Extensions.FileSystemGlobbing;
|
||||
using NBitcoin;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@ -349,6 +351,8 @@ retry:
|
||||
{
|
||||
defaultTranslatedKeys.Add(k);
|
||||
}
|
||||
|
||||
AddLocalizers(defaultTranslatedKeys, txt);
|
||||
}
|
||||
|
||||
// Go through all cshtml file, search for text-translate or ViewLocalizer usage
|
||||
@ -360,21 +364,11 @@ retry:
|
||||
{
|
||||
var filePath = file.FullName;
|
||||
var txt = File.ReadAllText(file.FullName);
|
||||
foreach (string localizer in new[] { "ViewLocalizer", "StringLocalizer" })
|
||||
{
|
||||
if (txt.Contains(localizer))
|
||||
{
|
||||
var matches = Regex.Matches(txt, localizer + "\\[\"(.*?)\"[\\],]");
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
defaultTranslatedKeys.Add(match.Groups[1].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
AddLocalizers(defaultTranslatedKeys, txt);
|
||||
|
||||
filePath = filePath.Replace(Path.Combine(soldir.FullName, "BTCPayServer"), "/");
|
||||
var item = engine.FileSystem.GetItem(filePath);
|
||||
|
||||
|
||||
var node = (DocumentIntermediateNode)engine.Process(item).Items[typeof(DocumentIntermediateNode)];
|
||||
var w = new TranslatedKeyNodeWalker(defaultTranslatedKeys, txt);
|
||||
w.Visit(node);
|
||||
@ -397,6 +391,24 @@ retry:
|
||||
content += defaultTranslation.Substring(endIdx);
|
||||
File.WriteAllText(path, content);
|
||||
}
|
||||
|
||||
private static void AddLocalizers(List<string> defaultTranslatedKeys, string txt)
|
||||
{
|
||||
foreach (string localizer in new[] { "ViewLocalizer", "StringLocalizer" })
|
||||
{
|
||||
if (txt.Contains(localizer))
|
||||
{
|
||||
var matches = Regex.Matches(txt, localizer + "\\[\"(.*?)\"[\\],]");
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
var k = match.Groups[1].Value;
|
||||
k = k.Replace("\\", "");
|
||||
defaultTranslatedKeys.Add(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DisplayNameWalker : CSharpSyntaxWalker
|
||||
{
|
||||
public List<string> Keys = new List<string>();
|
||||
|
@ -107,13 +107,13 @@
|
||||
@if (ViewData.IsCategoryActive(typeof(WalletsNavPages), scheme.WalletId.ToString()) || ViewData.IsPageActive([WalletsNavPages.Settings], scheme.WalletId.ToString()) || ViewData.IsPageActive([StoreNavPages.OnchainSettings], categoryId))
|
||||
{
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="WalletNav-Send" class="nav-link @ViewData.ActivePageClass([WalletsNavPages.Send, WalletsNavPages.PSBT], scheme.WalletId.ToString())" asp-area="" asp-controller="UIWallets" asp-action="WalletSend" asp-route-walletId="@scheme.WalletId">Send</a>
|
||||
<a id="WalletNav-Send" class="nav-link @ViewData.ActivePageClass([WalletsNavPages.Send, WalletsNavPages.PSBT], scheme.WalletId.ToString())" asp-area="" asp-controller="UIWallets" asp-action="WalletSend" asp-route-walletId="@scheme.WalletId" text-translate="true">Send</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="WalletNav-Receive" class="nav-link @ViewData.ActivePageClass(WalletsNavPages.Receive, scheme.WalletId.ToString())" asp-area="" asp-controller="UIWallets" asp-action="WalletReceive" asp-route-walletId="@scheme.WalletId">Receive</a>
|
||||
<a id="WalletNav-Receive" class="nav-link @ViewData.ActivePageClass(WalletsNavPages.Receive, scheme.WalletId.ToString())" asp-area="" asp-controller="UIWallets" asp-action="WalletReceive" asp-route-walletId="@scheme.WalletId" text-translate="true">Receive</a>
|
||||
</li>
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="WalletNav-Settings" class="nav-link @ViewData.ActivePageClass(WalletsNavPages.Settings, scheme.WalletId.ToString()) @ViewData.ActivePageClass(StoreNavPages.OnchainSettings, categoryId)" asp-area="" asp-controller="UIStores" asp-action="WalletSettings" asp-route-cryptoCode="@scheme.WalletId.CryptoCode" asp-route-storeId="@scheme.WalletId.StoreId">Settings</a>
|
||||
<a id="WalletNav-Settings" class="nav-link @ViewData.ActivePageClass(WalletsNavPages.Settings, scheme.WalletId.ToString()) @ViewData.ActivePageClass(StoreNavPages.OnchainSettings, categoryId)" asp-area="" asp-controller="UIStores" asp-action="WalletSettings" asp-route-cryptoCode="@scheme.WalletId.CryptoCode" asp-route-storeId="@scheme.WalletId.StoreId" text-translate="true">Settings</a>
|
||||
</li>
|
||||
<vc:ui-extension-point location="wallet-nav" model="@Model" />
|
||||
}
|
||||
@ -143,7 +143,7 @@
|
||||
@if (ViewData.IsPageActive([StoreNavPages.Lightning, StoreNavPages.LightningSettings], $"{Model.Store.Id}-{scheme.CryptoCode}"))
|
||||
{
|
||||
<li class="nav-item nav-item-sub">
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.LightningSettings))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.LightningSettings)" asp-controller="UIStores" asp-action="LightningSettings" asp-route-storeId="@Model.Store.Id" asp-route-cryptoCode="@scheme.CryptoCode">Settings</a>
|
||||
<a id="StoreNav-@(nameof(StoreNavPages.LightningSettings))" class="nav-link @ViewData.ActivePageClass(StoreNavPages.LightningSettings)" asp-controller="UIStores" asp-action="LightningSettings" asp-route-storeId="@Model.Store.Id" asp-route-cryptoCode="@scheme.CryptoCode" text-translate="true">Settings</a>
|
||||
</li>
|
||||
<vc:ui-extension-point location="lightning-nav" model="@Model"/>
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
}
|
||||
<div id="StoreLightningBalance-@Model.Store.Id" class="widget store-lightning-balance">
|
||||
<div class="d-flex gap-3 align-items-center justify-content-between mb-2">
|
||||
<h6>Lightning Balance</h6>
|
||||
<h6 text-translate="true">Lightning Balance</h6>
|
||||
@if (Model.CryptoCode != Model.DefaultCurrency && Model.Balance != null)
|
||||
{
|
||||
<div class="btn-group btn-group-sm gap-0 currency-toggle" role="group">
|
||||
@ -29,7 +29,7 @@
|
||||
<div class="d-flex align-items-baseline gap-1">
|
||||
<h3 class="d-inline-block me-1" data-balance="@Model.TotalOffchain" data-sensitive>@Model.TotalOffchain</h3>
|
||||
<span class="text-secondary fw-semibold text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> in channels
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> in channels", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
@Model.Balance.OffchainBalance.Opening
|
||||
</span>
|
||||
<span class="text-secondary text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> opening channels
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> opening channels", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@ -52,7 +52,7 @@
|
||||
@Model.Balance.OffchainBalance.Local
|
||||
</span>
|
||||
<span class="text-secondary text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> local balance
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> local balance", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@ -63,7 +63,7 @@
|
||||
@Model.Balance.OffchainBalance.Remote
|
||||
</span>
|
||||
<span class="text-secondary text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> remote balance
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> remote balance", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@ -74,7 +74,7 @@
|
||||
@Model.Balance.OffchainBalance.Closing
|
||||
</span>
|
||||
<span class="text-secondary text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> closing channels
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> closing channels", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@ -87,7 +87,7 @@
|
||||
<div class="d-flex align-items-baseline gap-1">
|
||||
<h3 class="d-inline-block me-1" data-balance="@Model.TotalOnchain" data-sensitive>@Model.TotalOnchain</h3>
|
||||
<span class="text-secondary fw-semibold text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> on-chain
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> on-chain", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
<div class="balance-details collapse" id="balanceDetailsOnchain">
|
||||
@ -98,7 +98,7 @@
|
||||
@Model.Balance.OnchainBalance.Confirmed
|
||||
</span>
|
||||
<span class="text-secondary text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> confirmed
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> confirmed", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@ -109,7 +109,7 @@
|
||||
@Model.Balance.OnchainBalance.Unconfirmed
|
||||
</span>
|
||||
<span class="text-secondary text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> unconfirmed
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> unconfirmed", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@ -120,7 +120,7 @@
|
||||
@Model.Balance.OnchainBalance.Reserved
|
||||
</span>
|
||||
<span class="text-secondary text-nowrap">
|
||||
<span class="currency">@Model.CryptoCode</span> reserved
|
||||
@ViewLocalizer["<span class=\"currency\">{0}</span> reserved", @Model.CryptoCode]
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@ -132,7 +132,7 @@
|
||||
{
|
||||
<button class="d-inline-flex align-items-center btn btn-link text-primary fw-semibold p-0 mt-3 ms-n1" type="button" data-bs-toggle="collapse" data-bs-target=".balance-details" aria-expanded="false" aria-controls="balanceDetailsOffchain balanceDetailsOnchain">
|
||||
<vc:icon symbol="caret-down"/>
|
||||
<span class="ms-1">Details</span>
|
||||
<span class="ms-1" text-translate="true">Details</span>
|
||||
</button>
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@
|
||||
{
|
||||
<div class="loading d-flex justify-content-center p-3">
|
||||
<div class="spinner-border text-light" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<span class="visually-hidden" text-translate="true">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
@ -4,14 +4,15 @@
|
||||
{
|
||||
<div id="StoreLightningServices-@Model.Store.Id" class="widget store-lightning-services">
|
||||
<header class="mb-4">
|
||||
<h6>Lightning Services</h6>
|
||||
<h6 text-translate="true">Lightning Services</h6>
|
||||
<a
|
||||
asp-controller="UIPublicLightningNodeInfo"
|
||||
asp-action="ShowLightningNodeInfo"app-top-items
|
||||
asp-route-cryptoCode="@Model.CryptoCode"
|
||||
asp-route-storeId="@Model.Store.Id"
|
||||
target="_blank"
|
||||
id="PublicNodeInfo">
|
||||
id="PublicNodeInfo"
|
||||
text-translate="true">
|
||||
Node Info
|
||||
</a>
|
||||
</header>
|
||||
|
@ -24,7 +24,7 @@
|
||||
{
|
||||
<div class="store-number">
|
||||
<header>
|
||||
<h6>Paid invoices in the last @Model.TimeframeDays days</h6>
|
||||
<h6 text-translate="true">@ViewLocalizer["Paid invoices in the last {0} days", @Model.TimeframeDays]</h6>
|
||||
@if (Model.PaidInvoices > 0)
|
||||
{
|
||||
<a asp-controller="UIInvoice" asp-action="ListInvoices" asp-route-storeId="@Model.Store.Id" permission="@Policies.CanViewInvoices">View All</a>
|
||||
@ -34,14 +34,14 @@
|
||||
</div>
|
||||
<div class="store-number">
|
||||
<header>
|
||||
<h6>Payouts Pending</h6>
|
||||
<a asp-controller="UIStorePullPayments" asp-action="Payouts" asp-route-storeId="@Model.Store.Id" permission="@Policies.CanManagePullPayments">Manage</a>
|
||||
<h6 text-translate="true">Payouts Pending</h6>
|
||||
<a asp-controller="UIStorePullPayments" asp-action="Payouts" asp-route-storeId="@Model.Store.Id" permission="@Policies.CanManagePullPayments" text-translate="true">Manage</a>
|
||||
</header>
|
||||
<div class="h3">@Model.PayoutsPending</div>
|
||||
</div>
|
||||
<div class="store-number">
|
||||
<header>
|
||||
<h6>Refunds Issued</h6>
|
||||
<h6 text-translate="true">Refunds Issued</h6>
|
||||
</header>
|
||||
<div class="h3">@Model.RefundsIssued</div>
|
||||
</div>
|
||||
|
@ -6,17 +6,17 @@
|
||||
|
||||
<div class="widget store-recent-invoices" id="StoreRecentInvoices-@Model.Store.Id">
|
||||
<header>
|
||||
<h3>Recent Invoices</h3>
|
||||
<h3 text-translate="true">Recent Invoices</h3>
|
||||
@if (Model.Invoices.Any())
|
||||
{
|
||||
<a asp-controller="UIInvoice" asp-action="ListInvoices" asp-route-storeId="@Model.Store.Id">View All</a>
|
||||
<a asp-controller="UIInvoice" asp-action="ListInvoices" asp-route-storeId="@Model.Store.Id" text-translate="true">View All</a>
|
||||
}
|
||||
</header>
|
||||
@if (Model.InitialRendering)
|
||||
{
|
||||
<div class="loading d-flex justify-content-center p-3">
|
||||
<div class="spinner-border text-light" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<span class="visually-hidden" text-translate="true">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
@ -36,10 +36,10 @@
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-125px">Date</th>
|
||||
<th class="text-nowrap">Invoice Id</th>
|
||||
<th>Status</th>
|
||||
<th class="text-end">Amount</th>
|
||||
<th class="w-125px" text-translate="true">Date</th>
|
||||
<th class="text-nowrap" text-translate="true">Invoice Id</th>
|
||||
<th text-translate="true">Status</th>
|
||||
<th class="text-end" text-translate="true">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -65,10 +65,10 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-secondary my-3">
|
||||
<p class="text-secondary my-3" text-translate="true">
|
||||
There are no recent invoices.
|
||||
</p>
|
||||
<a asp-controller="UIInvoice" asp-action="CreateInvoice" asp-route-storeId="@Model.Store.Id" class="fw-semibold">
|
||||
<a asp-controller="UIInvoice" asp-action="CreateInvoice" asp-route-storeId="@Model.Store.Id" class="fw-semibold" text-translate="true">
|
||||
Create Invoice
|
||||
</a>
|
||||
}
|
||||
|
@ -4,17 +4,17 @@
|
||||
|
||||
<div class="widget store-recent-transactions" id="StoreRecentTransactions-@Model.Store.Id">
|
||||
<header>
|
||||
<h3>Recent Transactions</h3>
|
||||
<h3 text-translate="true">Recent Transactions</h3>
|
||||
@if (Model.Transactions.Any())
|
||||
{
|
||||
<a asp-controller="UIWallets" asp-action="WalletTransactions" asp-route-walletId="@Model.WalletId">View All</a>
|
||||
<a asp-controller="UIWallets" asp-action="WalletTransactions" asp-route-walletId="@Model.WalletId" text-translate="true">View All</a>
|
||||
}
|
||||
</header>
|
||||
@if (Model.InitialRendering)
|
||||
{
|
||||
<div class="loading d-flex justify-content-center p-3">
|
||||
<div class="spinner-border text-light" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<span class="visually-hidden" text-translate="true">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
@ -34,10 +34,10 @@
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-125px">Date</th>
|
||||
<th>Transaction</th>
|
||||
<th>Labels</th>
|
||||
<th class="text-end">Amount</th>
|
||||
<th class="w-125px" text-translate="true">Date</th>
|
||||
<th text-translate="true">Transaction</th>
|
||||
<th text-translate="true">Labels</th>
|
||||
<th class="text-end" text-translate="true">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -90,7 +90,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-secondary mt-3 mb-0">
|
||||
<p class="text-secondary mt-3 mb-0" text-translate="true">
|
||||
There are no recent transactions.
|
||||
</p>
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
@inject BTCPayNetworkProvider NetworkProvider
|
||||
<div id="StoreWalletBalance-@Model.Store.Id" class="widget store-wallet-balance">
|
||||
<div class="d-flex gap-3 align-items-center justify-content-between mb-2">
|
||||
<h6>Wallet Balance</h6>
|
||||
<h6 text-translate="true">Wallet Balance</h6>
|
||||
@if (Model.CryptoCode != Model.DefaultCurrency)
|
||||
{
|
||||
<div class="btn-group btn-group-sm gap-0 currency-toggle" role="group">
|
||||
@ -39,7 +39,7 @@
|
||||
{
|
||||
<div class="ct-chart"></div>
|
||||
}
|
||||
else if (Model.Store.GetPaymentMethodConfig(PaymentTypes.CHAIN.GetPaymentMethodId(Model.CryptoCode)) is null)
|
||||
else if (Model.Store.GetPaymentMethodConfig(PaymentTypes.CHAIN.GetPaymentMethodId(Model.CryptoCode)) is null)
|
||||
{
|
||||
<p>
|
||||
We would like to show you a chart of your balance but you have not yet <a href="@Url.Action("SetupWallet", "UIStores", new {storeId = Model.Store.Id, cryptoCode = Model.CryptoCode})">configured a wallet</a>.
|
||||
|
@ -18,8 +18,10 @@ using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using MarkPayoutRequest = BTCPayServer.HostedServices.MarkPayoutRequest;
|
||||
using PayoutData = BTCPayServer.Data.PayoutData;
|
||||
@ -50,7 +52,10 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
public IStringLocalizer StringLocalizer { get; }
|
||||
|
||||
public UIStorePullPaymentsController(BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
IStringLocalizer stringLocalizer,
|
||||
PayoutMethodHandlerDictionary payoutHandlers,
|
||||
CurrencyNameTable currencyNameTable,
|
||||
DisplayFormatter displayFormatter,
|
||||
@ -62,6 +67,7 @@ namespace BTCPayServer.Controllers
|
||||
IAuthorizationService authorizationService)
|
||||
{
|
||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||
StringLocalizer = stringLocalizer;
|
||||
_payoutHandlers = payoutHandlers;
|
||||
_currencyNameTable = currencyNameTable;
|
||||
_displayFormatter = displayFormatter;
|
||||
@ -85,7 +91,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Message = "You must enable at least one payment method before creating a pull payment.",
|
||||
Message = StringLocalizer["You must enable at least one payment method before creating a pull payment."],
|
||||
Severity = StatusMessageModel.StatusSeverity.Error
|
||||
});
|
||||
return RedirectToAction(nameof(UIStoresController.Index), "UIStores", new { storeId });
|
||||
@ -119,25 +125,25 @@ namespace BTCPayServer.Controllers
|
||||
// them here to reflect user's selection so that they can correct their mistake
|
||||
model.PayoutMethodsItem =
|
||||
paymentMethodOptions.Select(id => new SelectListItem(id.ToString(), id.ToString(), false));
|
||||
ModelState.AddModelError(nameof(model.PayoutMethods), "You need at least one payout method");
|
||||
ModelState.AddModelError(nameof(model.PayoutMethods), StringLocalizer["You need at least one payout method"]);
|
||||
}
|
||||
if (_currencyNameTable.GetCurrencyData(model.Currency, false) is null)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.Currency), "Invalid currency");
|
||||
ModelState.AddModelError(nameof(model.Currency), StringLocalizer["Invalid currency"]);
|
||||
}
|
||||
if (model.Amount <= 0.0m)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.Amount), "The amount should be more than zero");
|
||||
ModelState.AddModelError(nameof(model.Amount), StringLocalizer["The amount should be more than zero"]);
|
||||
}
|
||||
if (model.Name.Length > 50)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.Name), "The name should be maximum 50 characters.");
|
||||
ModelState.AddModelError(nameof(model.Name), StringLocalizer["The name should be maximum 50 characters."]);
|
||||
}
|
||||
|
||||
var selectedPaymentMethodIds = model.PayoutMethods.Select(PayoutMethodId.Parse).ToArray();
|
||||
if (!selectedPaymentMethodIds.All(id => paymentMethodOptions.Contains(id)))
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.Name), "Not all payout methods are supported");
|
||||
ModelState.AddModelError(nameof(model.Name), StringLocalizer["Not all payout methods are supported"]);
|
||||
}
|
||||
if (!ModelState.IsValid)
|
||||
return View(model);
|
||||
@ -156,7 +162,7 @@ namespace BTCPayServer.Controllers
|
||||
});
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Message = "Pull payment request created",
|
||||
Message = StringLocalizer["Pull payment request created"],
|
||||
Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
return RedirectToAction(nameof(PullPayments), new { storeId });
|
||||
@ -198,7 +204,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Message = "You must enable at least one payment method before creating a pull payment.",
|
||||
Message = StringLocalizer["You must enable at least one payment method before creating a pull payment."],
|
||||
Severity = StatusMessageModel.StatusSeverity.Error
|
||||
});
|
||||
return RedirectToAction(nameof(UIStoresController.Index), "UIStores", new { storeId });
|
||||
@ -260,7 +266,7 @@ namespace BTCPayServer.Controllers
|
||||
string pullPaymentId)
|
||||
{
|
||||
return View("Confirm",
|
||||
new ConfirmModel("Archive pull payment", "Do you really want to archive the pull payment?", "Archive"));
|
||||
new ConfirmModel(StringLocalizer["Archive pull payment"], StringLocalizer["Do you really want to archive the pull payment?"], "Archive"));
|
||||
}
|
||||
|
||||
[HttpPost("stores/{storeId}/pull-payments/{pullPaymentId}/archive")]
|
||||
@ -298,7 +304,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Message = "No payout selected",
|
||||
Message = StringLocalizer["No payout selected"],
|
||||
Severity = StatusMessageModel.StatusSeverity.Error
|
||||
});
|
||||
return RedirectToAction(nameof(Payouts),
|
||||
@ -341,7 +347,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
this.TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Message = $"Rate unavailable: {rateResult.EvaluatedRule}",
|
||||
Message = StringLocalizer["Rate unavailable: {0}", rateResult.EvaluatedRule],
|
||||
Severity = StatusMessageModel.StatusSeverity.Error
|
||||
});
|
||||
failed = true;
|
||||
@ -379,7 +385,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Message = "Payouts approved",
|
||||
Message = StringLocalizer["Payouts approved"],
|
||||
Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
break;
|
||||
@ -391,7 +397,7 @@ namespace BTCPayServer.Controllers
|
||||
return await handler.InitiatePayment(payoutIds);
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Message = "Paying via this payment method is not supported",
|
||||
Message = StringLocalizer["Paying via this payment method is not supported"],
|
||||
Severity = StatusMessageModel.StatusSeverity.Error
|
||||
});
|
||||
break;
|
||||
@ -430,7 +436,7 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Message = "Payouts marked as paid",
|
||||
Message = StringLocalizer["Payouts marked as paid"],
|
||||
Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
break;
|
||||
@ -441,7 +447,7 @@ namespace BTCPayServer.Controllers
|
||||
new PullPaymentHostedService.CancelRequest(payoutIds, new[] { storeId }));
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||
{
|
||||
Message = "Payouts archived",
|
||||
Message = StringLocalizer["Payouts archived"],
|
||||
Severity = StatusMessageModel.StatusSeverity.Success
|
||||
});
|
||||
break;
|
||||
@ -482,7 +488,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Message = "You must enable at least one payment method before creating a payout.",
|
||||
Message = StringLocalizer["You must enable at least one payment method before creating a payout."],
|
||||
Severity = StatusMessageModel.StatusSeverity.Error
|
||||
});
|
||||
return RedirectToAction(nameof(UIStoresController.Index), "UIStores", new { storeId });
|
||||
|
@ -176,7 +176,7 @@ public partial class UIStoresController
|
||||
vm.AvailableExchanges = sources;
|
||||
var exchange = storeBlob.GetPreferredExchange(_defaultRules);
|
||||
var chosenSource = sources.First(r => r.Id == exchange);
|
||||
vm.Exchanges = UIUserStoresController.GetExchangesSelectList(_rateFactory, _defaultRules, storeBlob);
|
||||
vm.Exchanges = _userStoresController.GetExchangesSelectList(storeBlob);
|
||||
vm.PreferredExchange = vm.Exchanges.SelectedValue as string;
|
||||
vm.PreferredResolvedExchange = chosenSource.Id;
|
||||
vm.RateSource = chosenSource.Url;
|
||||
|
@ -58,6 +58,7 @@ public partial class UIStoresController : Controller
|
||||
DefaultRulesCollection defaultRules,
|
||||
EmailSenderFactory emailSenderFactory,
|
||||
WalletFileParsers onChainWalletParsers,
|
||||
UIUserStoresController userStoresController,
|
||||
UriResolver uriResolver,
|
||||
SettingsRepository settingsRepository,
|
||||
CurrencyNameTable currencyNameTable,
|
||||
@ -82,6 +83,7 @@ public partial class UIStoresController : Controller
|
||||
_externalServiceOptions = externalServiceOptions;
|
||||
_emailSenderFactory = emailSenderFactory;
|
||||
_onChainWalletParsers = onChainWalletParsers;
|
||||
_userStoresController = userStoresController;
|
||||
_uriResolver = uriResolver;
|
||||
_settingsRepository = settingsRepository;
|
||||
_currencyNameTable = currencyNameTable;
|
||||
@ -115,6 +117,7 @@ public partial class UIStoresController : Controller
|
||||
private readonly IOptions<ExternalServicesOptions> _externalServiceOptions;
|
||||
private readonly EmailSenderFactory _emailSenderFactory;
|
||||
private readonly WalletFileParsers _onChainWalletParsers;
|
||||
private readonly UIUserStoresController _userStoresController;
|
||||
private readonly UriResolver _uriResolver;
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly IHtmlHelper _html;
|
||||
|
@ -2,6 +2,7 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Data;
|
||||
@ -12,7 +13,9 @@ using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Localization;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Controllers
|
||||
{
|
||||
@ -21,6 +24,7 @@ namespace BTCPayServer.Controllers
|
||||
public class UIUserStoresController : Controller
|
||||
{
|
||||
private readonly StoreRepository _repo;
|
||||
private readonly IStringLocalizer StringLocalizer;
|
||||
private readonly SettingsRepository _settingsRepository;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly DefaultRulesCollection _defaultRules;
|
||||
@ -31,10 +35,12 @@ namespace BTCPayServer.Controllers
|
||||
UserManager<ApplicationUser> userManager,
|
||||
DefaultRulesCollection defaultRules,
|
||||
StoreRepository storeRepository,
|
||||
IStringLocalizer stringLocalizer,
|
||||
RateFetcher rateFactory,
|
||||
SettingsRepository settingsRepository)
|
||||
{
|
||||
_repo = storeRepository;
|
||||
StringLocalizer = stringLocalizer;
|
||||
_userManager = userManager;
|
||||
_defaultRules = defaultRules;
|
||||
_rateFactory = rateFactory;
|
||||
@ -95,7 +101,7 @@ namespace BTCPayServer.Controllers
|
||||
store.SetStoreBlob(blob);
|
||||
await _repo.CreateStore(GetUserId(), store);
|
||||
CreatedStoreId = store.Id;
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Store successfully created";
|
||||
TempData.SetStatusSuccess(StringLocalizer["Store successfully created"]);
|
||||
return RedirectToAction(nameof(UIStoresController.Index), "UIStores", new
|
||||
{
|
||||
storeId = store.Id
|
||||
@ -109,7 +115,7 @@ namespace BTCPayServer.Controllers
|
||||
var store = HttpContext.GetStoreData();
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
return View("Confirm", new ConfirmModel($"Delete store {store.StoreName}", "This store will still be accessible to users sharing it", "Delete"));
|
||||
return View("Confirm", new ConfirmModel(StringLocalizer["Delete store {0}", store.StoreName], StringLocalizer["This store will still be accessible to users sharing it"], "Delete"));
|
||||
}
|
||||
|
||||
[HttpPost("{storeId}/me/delete")]
|
||||
@ -121,24 +127,23 @@ namespace BTCPayServer.Controllers
|
||||
if (store == null)
|
||||
return NotFound();
|
||||
await _repo.RemoveStore(storeId, userId);
|
||||
TempData[WellKnownTempData.SuccessMessage] = "Store removed successfully";
|
||||
TempData.SetStatusSuccess(StringLocalizer["Store removed successfully"]);
|
||||
return RedirectToAction(nameof(UIHomeController.Index), "UIHome");
|
||||
}
|
||||
|
||||
private string GetUserId() => _userManager.GetUserId(User);
|
||||
|
||||
private SelectList GetExchangesSelectList(StoreBlob storeBlob) => GetExchangesSelectList(_rateFactory, _defaultRules, storeBlob);
|
||||
internal static SelectList GetExchangesSelectList(RateFetcher rateFetcher, DefaultRulesCollection defaultRules, StoreBlob storeBlob)
|
||||
internal SelectList GetExchangesSelectList(StoreBlob storeBlob)
|
||||
{
|
||||
if (storeBlob is null)
|
||||
storeBlob = new StoreBlob();
|
||||
var defaultExchange = defaultRules.GetRecommendedExchange(storeBlob.DefaultCurrency);
|
||||
var exchanges = rateFetcher.RateProviderFactory
|
||||
var defaultExchange = _defaultRules.GetRecommendedExchange(storeBlob.DefaultCurrency);
|
||||
var exchanges = _rateFactory.RateProviderFactory
|
||||
.AvailableRateProviders
|
||||
.OrderBy(s => s.Id, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
var exchange = exchanges.First(e => e.Id == defaultExchange);
|
||||
exchanges.Insert(0, new(null, $"Recommendation ({exchange.DisplayName})", ""));
|
||||
exchanges.Insert(0, new(null, StringLocalizer["Recommendation ({0})", exchange.DisplayName], ""));
|
||||
var chosen = exchanges.FirstOrDefault(f => f.Id == storeBlob.PreferredExchange) ?? exchanges.First();
|
||||
return new SelectList(exchanges, nameof(chosen.Id), nameof(chosen.DisplayName), chosen.Id);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ using BTCPayServer.Payments.Bitcoin;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Reporting;
|
||||
using BTCPayServer.Services.Wallets;
|
||||
@ -291,7 +292,17 @@ namespace BTCPayServer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#nullable enable
|
||||
public static IServiceCollection AddDefaultTransactions(this IServiceCollection services, params string[] keyValues)
|
||||
{
|
||||
return services.AddDefaultTransactions(keyValues.Select(k => KeyValuePair.Create<string, string?>(k, string.Empty)).ToArray());
|
||||
}
|
||||
public static IServiceCollection AddDefaultTransactions(this IServiceCollection services, params KeyValuePair<string, string?>[] keyValues)
|
||||
{
|
||||
services.AddSingleton<IDefaultTransactionProvider>(new InMemoryDefaultTransactionProvider(keyValues));
|
||||
return services;
|
||||
}
|
||||
#nullable restore
|
||||
public static IServiceCollection AddUIExtension(this IServiceCollection services, string location, string partialViewName)
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
@ -631,6 +631,7 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
|
||||
(IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentLinkExtension), new object[] { network, pmi }));
|
||||
services.AddSingleton<ICheckoutModelExtension>(provider =>
|
||||
(BitcoinCheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinCheckoutModelExtension), new object[] { network, pmi }));
|
||||
services.AddDefaultTransactions(network.DisplayName);
|
||||
services.AddSingleton<IPaymentMethodBitpayAPIExtension>(provider =>
|
||||
(IPaymentMethodBitpayAPIExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentMethodBitpayAPIExtension), new object[] { pmi }));
|
||||
|
||||
|
@ -7,6 +7,7 @@ using BTCPayServer.Models.InvoicingModels;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using NBitcoin;
|
||||
using NBitcoin.DataEncoders;
|
||||
|
||||
@ -17,6 +18,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
public const string CheckoutBodyComponentName = "BitcoinCheckoutBody";
|
||||
private readonly PaymentMethodHandlerDictionary _handlers;
|
||||
private readonly BTCPayNetwork _Network;
|
||||
private readonly IStringLocalizer StringLocalizer;
|
||||
private readonly DisplayFormatter _displayFormatter;
|
||||
private readonly IPaymentLinkExtension paymentLinkExtension;
|
||||
private readonly IPaymentLinkExtension? lnPaymentLinkExtension;
|
||||
@ -26,6 +28,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
public BitcoinCheckoutModelExtension(
|
||||
PaymentMethodId paymentMethodId,
|
||||
BTCPayNetwork network,
|
||||
IStringLocalizer stringLocalizer,
|
||||
IEnumerable<IPaymentLinkExtension> paymentLinkExtensions,
|
||||
DisplayFormatter displayFormatter,
|
||||
PaymentMethodHandlerDictionary handlers)
|
||||
@ -33,6 +36,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
PaymentMethodId = paymentMethodId;
|
||||
_handlers = handlers;
|
||||
_Network = network;
|
||||
StringLocalizer = stringLocalizer;
|
||||
_displayFormatter = displayFormatter;
|
||||
paymentLinkExtension = paymentLinkExtensions.Single(p => p.PaymentMethodId == PaymentMethodId);
|
||||
var lnPmi = PaymentTypes.LN.GetPaymentMethodId(network.CryptoCode);
|
||||
@ -41,7 +45,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
lnurlPaymentLinkExtension = paymentLinkExtensions.SingleOrDefault(p => p.PaymentMethodId == lnurlPmi);
|
||||
_bech32Prefix = network.NBitcoinNetwork.GetBech32Encoder(Bech32Type.WITNESS_PUBKEY_ADDRESS, false) is { } enc ? Encoders.ASCII.EncodeData(enc.HumanReadablePart) : null;
|
||||
}
|
||||
public string DisplayName => _Network.DisplayName;
|
||||
public string DisplayName => StringLocalizer[_Network.DisplayName];
|
||||
public string Image => _Network.CryptoImagePath;
|
||||
public string Badge => "";
|
||||
public PaymentMethodId PaymentMethodId { get; }
|
||||
|
@ -6,6 +6,7 @@ using BTCPayServer.Services;
|
||||
using Org.BouncyCastle.Crypto.Modes.Gcm;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace BTCPayServer.Payments.Lightning
|
||||
{
|
||||
@ -14,27 +15,31 @@ namespace BTCPayServer.Payments.Lightning
|
||||
public const string CheckoutBodyComponentName = "LightningCheckoutBody";
|
||||
private readonly DisplayFormatter _displayFormatter;
|
||||
IPaymentLinkExtension _PaymentLinkExtension;
|
||||
private readonly bool isBTC;
|
||||
|
||||
public LNCheckoutModelExtension(
|
||||
PaymentMethodId paymentMethodId,
|
||||
BTCPayNetwork network,
|
||||
DisplayFormatter displayFormatter,
|
||||
IEnumerable<IPaymentLinkExtension> paymentLinkExtensions,
|
||||
IStringLocalizer stringLocalizer,
|
||||
PaymentMethodHandlerDictionary handlers)
|
||||
{
|
||||
Network = network;
|
||||
_displayFormatter = displayFormatter;
|
||||
StringLocalizer = stringLocalizer;
|
||||
Handlers = handlers;
|
||||
PaymentMethodId = paymentMethodId;
|
||||
_PaymentLinkExtension = paymentLinkExtensions.Single(p => p.PaymentMethodId == PaymentMethodId);
|
||||
var isBTC = PaymentTypes.LN.GetPaymentMethodId("BTC") == paymentMethodId;
|
||||
DisplayName = isBTC ? "Lightning" : $"Lightning ({Network.DisplayName})";
|
||||
isBTC = PaymentTypes.LN.GetPaymentMethodId("BTC") == paymentMethodId;
|
||||
}
|
||||
|
||||
public BTCPayNetwork Network { get; }
|
||||
public IStringLocalizer StringLocalizer { get; }
|
||||
public PaymentMethodHandlerDictionary Handlers { get; }
|
||||
public PaymentMethodId PaymentMethodId { get; }
|
||||
|
||||
public string DisplayName { get; }
|
||||
public string DisplayName => isBTC ? StringLocalizer["Lightning"] : StringLocalizer["Lightning ({0})", Network.DisplayName];
|
||||
|
||||
public string Image => Network.LightningImagePath;
|
||||
public string Badge => "⚡";
|
||||
@ -50,7 +55,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
if (context.Model.InvoiceBitcoinUrl is not null)
|
||||
context.Model.InvoiceBitcoinUrlQR = $"lightning:{context.Model.InvoiceBitcoinUrl.ToUpperInvariant()?.Substring("LIGHTNING:".Length)}";
|
||||
context.Model.PeerInfo = handler.ParsePaymentPromptDetails(paymentPrompt.Details).NodeInfo;
|
||||
if (context.StoreBlob.LightningAmountInSatoshi && context.Model.PaymentMethodCurrency == "BTC")
|
||||
if (context.StoreBlob.LightningAmountInSatoshi && isBTC)
|
||||
{
|
||||
BitcoinCheckoutModelExtension.PreparePaymentModelForAmountInSats(context.Model, paymentPrompt.Rate, _displayFormatter);
|
||||
}
|
||||
|
@ -19,16 +19,35 @@ using static BTCPayServer.Services.LocalizerService;
|
||||
|
||||
namespace BTCPayServer.Services
|
||||
{
|
||||
public interface IDefaultTransactionProvider
|
||||
{
|
||||
Task<KeyValuePair<string, string?>[]> GetDefaultTransaction();
|
||||
}
|
||||
public class InMemoryDefaultTransactionProvider : IDefaultTransactionProvider
|
||||
{
|
||||
private readonly KeyValuePair<string, string?>[] _values;
|
||||
|
||||
public InMemoryDefaultTransactionProvider(KeyValuePair<string, string?>[] values)
|
||||
{
|
||||
_values = values;
|
||||
}
|
||||
public Task<KeyValuePair<string, string?>[]> GetDefaultTransaction()
|
||||
{
|
||||
return Task.FromResult(_values);
|
||||
}
|
||||
}
|
||||
public class LocalizerService
|
||||
{
|
||||
public LocalizerService(
|
||||
ILogger<LocalizerService> logger,
|
||||
ApplicationDbContextFactory contextFactory,
|
||||
ISettingsAccessor<PoliciesSettings> settingsAccessor)
|
||||
ISettingsAccessor<PoliciesSettings> settingsAccessor,
|
||||
IEnumerable<IDefaultTransactionProvider> defaultTransactionProviders)
|
||||
{
|
||||
_logger = logger;
|
||||
_ContextFactory = contextFactory;
|
||||
_settingsAccessor = settingsAccessor;
|
||||
_defaultTransactionProviders = defaultTransactionProviders;
|
||||
_LoadedTranslations = new LoadedTranslations(Translations.Default, Translations.Default, Translations.DefaultLanguage);
|
||||
}
|
||||
|
||||
@ -39,6 +58,7 @@ namespace BTCPayServer.Services
|
||||
private readonly ILogger<LocalizerService> _logger;
|
||||
private readonly ApplicationDbContextFactory _ContextFactory;
|
||||
private readonly ISettingsAccessor<PoliciesSettings> _settingsAccessor;
|
||||
private readonly IEnumerable<IDefaultTransactionProvider> _defaultTransactionProviders;
|
||||
|
||||
/// <summary>
|
||||
/// Load the translation of the server into memory
|
||||
@ -69,7 +89,18 @@ namespace BTCPayServer.Services
|
||||
{
|
||||
dict_id = dictionaryName,
|
||||
});
|
||||
var fallback = new Translations(all.Where(a => a.fallback).Select(o => KeyValuePair.Create(o.sentence, o.translation)), Translations.Default);
|
||||
var defaultDict = Translations.Default;
|
||||
var loading = _defaultTransactionProviders.Select(d => d.GetDefaultTransaction()).ToArray();
|
||||
Dictionary<string, string?> additionalDefault = new();
|
||||
foreach (var defaultProvider in loading)
|
||||
{
|
||||
foreach (var kv in await defaultProvider)
|
||||
{
|
||||
additionalDefault.TryAdd(kv.Key, string.IsNullOrEmpty(kv.Value) ? kv.Key : kv.Value);
|
||||
}
|
||||
}
|
||||
defaultDict = new Translations(additionalDefault, defaultDict);
|
||||
var fallback = new Translations(all.Where(a => a.fallback).Select(o => KeyValuePair.Create(o.sentence, o.translation)), defaultDict);
|
||||
var translations = new Translations(all.Where(a => !a.fallback).Select(o => KeyValuePair.Create(o.sentence, o.translation)), fallback);
|
||||
return new LoadedTranslations(translations, fallback, dictionaryName);
|
||||
}
|
||||
|
@ -14,7 +14,17 @@ namespace BTCPayServer.Services
|
||||
{
|
||||
"... on every payment": "",
|
||||
"... only if the customer makes more than one payment for the invoice": "",
|
||||
"<span class=\"currency\">{0}</span> closing channels": "",
|
||||
"<span class=\"currency\">{0}</span> confirmed": "",
|
||||
"<span class=\"currency\">{0}</span> in channels": "",
|
||||
"<span class=\"currency\">{0}</span> local balance": "",
|
||||
"<span class=\"currency\">{0}</span> on-chain": "",
|
||||
"<span class=\"currency\">{0}</span> opening channels": "",
|
||||
"<span class=\"currency\">{0}</span> remote balance": "",
|
||||
"<span class=\"currency\">{0}</span> reserved": "",
|
||||
"<span class=\"currency\">{0}</span> unconfirmed": "",
|
||||
"A given currency pair match the most specific rule. If two rules are matching and are as specific, the first rule will be chosen.": "",
|
||||
"A self-hosted, open-source bitcoin payment processor.": "",
|
||||
"Access Tokens": "",
|
||||
"Account": "",
|
||||
"Account key": "",
|
||||
@ -48,6 +58,7 @@ namespace BTCPayServer.Services
|
||||
"Application": "",
|
||||
"Apply the brand color to the store's backend as well": "",
|
||||
"Approve": "",
|
||||
"Archive pull payment": "",
|
||||
"Archive this store": "",
|
||||
"At Least One": "",
|
||||
"At Least Ten": "",
|
||||
@ -62,6 +73,7 @@ namespace BTCPayServer.Services
|
||||
"blocks": "",
|
||||
"Brand Color": "",
|
||||
"Branding": "",
|
||||
"BTCPay Server currently supports:": "",
|
||||
"But now, what if you want to support <code>DOGE</code>? The problem with <code>DOGE</code> is that most exchange do not have any pair for it. But <code>bitpay</code> has a <code>DOGE_BTC</code> pair. <br />\r\n Luckily, the rule engine allow you to reference rules:": "",
|
||||
"Buyer Email": "",
|
||||
"Callback Notification URL": "",
|
||||
@ -79,6 +91,8 @@ namespace BTCPayServer.Services
|
||||
"Confirm password": "",
|
||||
"Connect an existing wallet": "",
|
||||
"Connect hardware wallet": "",
|
||||
"Connect to a Lightning node": "",
|
||||
"Connection configuration for your custom Lightning node:": "",
|
||||
"Connection string": "",
|
||||
"Consider the invoice paid even if the paid amount is … % less than expected": "",
|
||||
"Consider the invoice settled when the payment transaction …": "",
|
||||
@ -89,6 +103,7 @@ namespace BTCPayServer.Services
|
||||
"Create": "",
|
||||
"Create a new app": "",
|
||||
"Create a new wallet": "",
|
||||
"Create account": "",
|
||||
"Create Account": "",
|
||||
"Create Form": "",
|
||||
"Create Invoice": "",
|
||||
@ -97,6 +112,7 @@ namespace BTCPayServer.Services
|
||||
"Create Store": "",
|
||||
"Create Webhook": "",
|
||||
"Create your account": "",
|
||||
"Create your store": "",
|
||||
"Crowdfund": "",
|
||||
"Currency": "",
|
||||
"Current password": "",
|
||||
@ -107,18 +123,21 @@ namespace BTCPayServer.Services
|
||||
"Custom Theme Extension Type": "",
|
||||
"Custom Theme File": "",
|
||||
"Dashboard": "",
|
||||
"Date": "",
|
||||
"days": "",
|
||||
"Default currency": "",
|
||||
"Default Currency Pairs": "",
|
||||
"Default language on checkout": "",
|
||||
"Default payment method on checkout": "",
|
||||
"Default role for users on a new store": "",
|
||||
"Delete store {0}": "",
|
||||
"Delete this store": "",
|
||||
"Derivation scheme": "",
|
||||
"Derivation scheme format": "",
|
||||
"Description": "",
|
||||
"Description template of the lightning invoice": "",
|
||||
"Destination Address": "",
|
||||
"Details": "",
|
||||
"Dictionaries": "",
|
||||
"Dictionaries enable you to translate the BTCPay Server backend into different languages.": "",
|
||||
"Dictionary": "",
|
||||
@ -136,10 +155,14 @@ namespace BTCPayServer.Services
|
||||
"Display Title": "",
|
||||
"Disqus Shortname": "",
|
||||
"Do not allow additional contributions after target has been reached": "",
|
||||
"Do not photograph it. Do not store it digitally.": "",
|
||||
"Do not photograph the recovery phrase, and do not store it digitally.": "",
|
||||
"Do you really want to archive the pull payment?": "",
|
||||
"Does not extend a BTCPay Server theme, fully custom": "",
|
||||
"Domain": "",
|
||||
"Domain name": "",
|
||||
"Don't create UTXO change": "",
|
||||
"Done": "",
|
||||
"Email": "",
|
||||
"Email address": "",
|
||||
"Email confirmation required": "",
|
||||
@ -188,27 +211,40 @@ namespace BTCPayServer.Services
|
||||
"However, explicitely setting specific pairs like this can be a bit difficult. Instead, you can define a rule <code>X_X</code> which will match any currency pair. The following example will use <code>kraken</code> for getting the rate of any currency pair.": "",
|
||||
"I don't have a wallet": "",
|
||||
"I have a wallet": "",
|
||||
"I have written down my recovery phrase and stored it in a secure location": "",
|
||||
"If a translation isn’t available in the new dictionary, it will be searched in the fallback.": "",
|
||||
"If you lose it or write it down incorrectly, you may permanently lose access to your funds.": "",
|
||||
"If you lose it or write it down incorrectly, you will permanently lose access to your funds.": "",
|
||||
"Image": "",
|
||||
"Import {0} Wallet": "",
|
||||
"Import an existing hardware or software wallet": "",
|
||||
"Import wallet file": "",
|
||||
"Import your public keys using our Vault application": "",
|
||||
"Input the key string manually": "",
|
||||
"Invalid currency": "",
|
||||
"Invitation URL": "",
|
||||
"Invoice currency": "",
|
||||
"Invoice expires if the full amount has not been paid after …": "",
|
||||
"Invoice Id": "",
|
||||
"Invoice metadata": "",
|
||||
"Invoices": "",
|
||||
"Is administrator?": "",
|
||||
"Is signing key": "",
|
||||
"Is unconfirmed": "",
|
||||
"It is secure, private, censorship-resistant and free.": "",
|
||||
"It is worth noting that the inverses of those pairs are automatically supported as well.<br />\r\n It means that the rule <code>USD_DOGE = 1 / DOGE_USD</code> implicitely exists.": "",
|
||||
"Item Description": "",
|
||||
"Keypad": "",
|
||||
"Labels": "",
|
||||
"Let's get started": "",
|
||||
"Lightning": "",
|
||||
"Lightning ({0})": "",
|
||||
"Lightning Address": "",
|
||||
"Lightning Balance": "",
|
||||
"Lightning node (LNURL Auth)": "",
|
||||
"Lightning Services": "",
|
||||
"LNURL Classic Mode": "",
|
||||
"Loading...": "",
|
||||
"Local File System": "",
|
||||
"Log in": "",
|
||||
"Login Codes": "",
|
||||
@ -217,6 +253,7 @@ namespace BTCPayServer.Services
|
||||
"Logs": "",
|
||||
"Maintenance": "",
|
||||
"Make Crowdfund Public": "",
|
||||
"Manage": "",
|
||||
"Manage Account": "",
|
||||
"Manage Plugins": "",
|
||||
"Master fingerprint": "",
|
||||
@ -228,11 +265,15 @@ namespace BTCPayServer.Services
|
||||
"Never add network fee": "",
|
||||
"New password": "",
|
||||
"Next": "",
|
||||
"No payout selected": "",
|
||||
"No scope": "",
|
||||
"Node Info": "",
|
||||
"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": "",
|
||||
"Non-admins can use the Internal Lightning Node for their Store": "",
|
||||
"Non-admins cannot access the User Creation API Endpoint": "",
|
||||
"Not all payout methods are supported": "",
|
||||
"Not recommended": "",
|
||||
"Notification Email": "",
|
||||
"Notification URL": "",
|
||||
@ -241,18 +282,27 @@ namespace BTCPayServer.Services
|
||||
"Optional seed passphrase": "",
|
||||
"Order Id": "",
|
||||
"Override the block explorers used": "",
|
||||
"Paid invoices in the last {0} days": "",
|
||||
"Pair to": "",
|
||||
"Password": "",
|
||||
"Password (leave blank to generate invite-link)": "",
|
||||
"Pay Button": "",
|
||||
"Paying via this payment method is not supported": "",
|
||||
"PayJoin BIP21": "",
|
||||
"Payment": "",
|
||||
"Payment invalid if transactions fails to confirm … after invoice expiration": "",
|
||||
"Payment Requests": "",
|
||||
"Payments": "",
|
||||
"Payout Methods": "",
|
||||
"Payout Processors": "",
|
||||
"Payouts": "",
|
||||
"Payouts approved": "",
|
||||
"Payouts archived": "",
|
||||
"Payouts marked as paid": "",
|
||||
"Payouts Pending": "",
|
||||
"Permissions": "",
|
||||
"Please enable JavaScript for this option to be available": "",
|
||||
"Please make sure to also write down your passphrase.": "",
|
||||
"Please note that creating a hot wallet is not supported by this instance for non administrators.": "",
|
||||
"Plugin server": "",
|
||||
"Plugins": "",
|
||||
@ -261,6 +311,7 @@ namespace BTCPayServer.Services
|
||||
"Policies": "",
|
||||
"Preferred Price Source": "",
|
||||
"Print display": "",
|
||||
"Process approved payouts instantly": "",
|
||||
"Product list": "",
|
||||
"Product list with cart": "",
|
||||
"Profile Picture": "",
|
||||
@ -268,15 +319,22 @@ namespace BTCPayServer.Services
|
||||
"PSBT content": "",
|
||||
"PSBT to combine with…": "",
|
||||
"Public Key": "",
|
||||
"Pull payment request created": "",
|
||||
"Pull Payments": "",
|
||||
"Rate Rules": "",
|
||||
"Rate script allows you to express precisely how you want to calculate rates for currency pairs.": "",
|
||||
"Rate unavailable: {0}": "",
|
||||
"Rates": "",
|
||||
"Receive": "",
|
||||
"Recent Invoices": "",
|
||||
"Recent Transactions": "",
|
||||
"Recommendation ({0})": "",
|
||||
"Recommended": "",
|
||||
"Recommended fee confirmation target blocks": "",
|
||||
"Recovery Code": "",
|
||||
"Redirect invoice to redirect url automatically after paid": "",
|
||||
"Redirect URL": "",
|
||||
"Refunds Issued": "",
|
||||
"Register": "",
|
||||
"Remember me": "",
|
||||
"Remember this machine": "",
|
||||
@ -298,10 +356,12 @@ namespace BTCPayServer.Services
|
||||
"Scope": "",
|
||||
"Scripting": "",
|
||||
"Search engines can index this site": "",
|
||||
"Secure your recovery phrase": "",
|
||||
"Security device (FIDO2)": "",
|
||||
"Select": "",
|
||||
"Select the Default Currency during Store Creation": "",
|
||||
"Select the payout method used for refund": "",
|
||||
"Send": "",
|
||||
"Send invitation email": "",
|
||||
"Send test webhook": "",
|
||||
"Server Name": "",
|
||||
@ -309,6 +369,8 @@ namespace BTCPayServer.Services
|
||||
"Services": "",
|
||||
"Set Password": "",
|
||||
"Set to default settings": "",
|
||||
"Set up a Lightning node": "",
|
||||
"Set up a wallet": "",
|
||||
"Settings": "",
|
||||
"Setup {0} Wallet": "",
|
||||
"Shop Name": "",
|
||||
@ -326,28 +388,46 @@ namespace BTCPayServer.Services
|
||||
"Specify the amount and currency for the refund": "",
|
||||
"Start date": "",
|
||||
"Starting index": "",
|
||||
"Status": "",
|
||||
"Store": "",
|
||||
"Store Id": "",
|
||||
"Store Name": "",
|
||||
"Store removed successfully": "",
|
||||
"Store Settings": "",
|
||||
"Store Speed Policy": "",
|
||||
"Store successfully created": "",
|
||||
"Store Website": "",
|
||||
"Store: {0}": "",
|
||||
"Submit": "",
|
||||
"Subtract fees from amount": "",
|
||||
"Support URL": "",
|
||||
"Supported by BlueWallet, Cobo Vault, Passport and Specter DIY": "",
|
||||
"Supported Transaction Currencies": "",
|
||||
"Target Amount": "",
|
||||
"Test connection": "",
|
||||
"Test Email": "",
|
||||
"Test Results:": "",
|
||||
"Testing": "",
|
||||
"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": "",
|
||||
"The amount should be more than zero": "",
|
||||
"The combination of words below are called your recovery phrase.\r\n The recovery phrase allows you to access and restore your wallet.\r\n Write them down on a piece of paper in the exact order:": "",
|
||||
"The following methods assume that you already have an existing wallet created and backed up.": "",
|
||||
"The name should be maximum 50 characters.": "",
|
||||
"The recommended price source gets chosen based on the default currency.": "",
|
||||
"The recovery phrase is a backup that allows you to restore your wallet in case of a server crash.": "",
|
||||
"The recovery phrase will also be stored on the server as a hot wallet.": "",
|
||||
"The recovery phrase will be permanently erased from the server.": "",
|
||||
"The script language is composed of several rules composed of a currency pair and a mathematic expression.\r\n The example below will use <code>kraken</code> for both <code>LTC_USD</code> and <code>BTC_USD</code> pairs.": "",
|
||||
"Theme": "",
|
||||
"There are no recent invoices.": "",
|
||||
"There are no recent transactions.": "",
|
||||
"This store is ready to accept transactions, good job!": "",
|
||||
"This store will still be accessible to users sharing it": "",
|
||||
"Tip percentage amounts (comma separated)": "",
|
||||
"To start accepting payments, set up a wallet or a Lightning node.": "",
|
||||
"Transaction": "",
|
||||
"Translations": "",
|
||||
"Two-Factor Authentication": "",
|
||||
"Unarchive this store": "",
|
||||
@ -357,14 +437,19 @@ namespace BTCPayServer.Services
|
||||
"Upload a file exported from your wallet": "",
|
||||
"Upload PSBT from file…": "",
|
||||
"Url of the Dynamic DNS service you are using": "",
|
||||
"Use custom node": "",
|
||||
"Use custom theme": "",
|
||||
"Use internal node": "",
|
||||
"Use SSL": "",
|
||||
"User can input custom amount": "",
|
||||
"User can input discount in %": "",
|
||||
"Users": "",
|
||||
"Using the BTCPay Server internal node for this store requires no further configuration. Click the save button below to start accepting Bitcoin through the Lightning Network.": "",
|
||||
"UTXOs to spend from": "",
|
||||
"Verification Code": "",
|
||||
"View All": "",
|
||||
"View-Only Wallet File": "",
|
||||
"Wallet Balance": "",
|
||||
"Wallet file": "",
|
||||
"Wallet file content": "",
|
||||
"Wallet Keys File": "",
|
||||
@ -376,8 +461,12 @@ namespace BTCPayServer.Services
|
||||
"Webhooks": "",
|
||||
"Welcome to {0}": "",
|
||||
"With <code>DOGE_USD</code> will be expanded to <code>bitpay(DOGE_BTC) * kraken(BTC_USD)</code>. And <code>DOGE_CAD</code> will be expanded to <code>bitpay(DOGE_BTC) * ndax(BTC_CAD)</code>. <br />\r\n However, we advise you to write it that way to increase coverage so that <code>DOGE_BTC</code> is also supported:": "",
|
||||
"You must enable at least one payment method before creating a payout.": "",
|
||||
"You must enable at least one payment method before creating a pull payment.": "",
|
||||
"You need at least one payout method": "",
|
||||
"You really should not type your seed into a device that is connected to the internet.": "",
|
||||
"Your dynamic DNS hostname": "",
|
||||
"Your instance administrator has disabled the use of the Internal node for non-admin users.": "",
|
||||
"Zero Confirmation": ""
|
||||
}
|
||||
""";
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model ErrorViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
ViewData["Title"] = ViewLocalizer["Error"];
|
||||
}
|
||||
|
||||
<h1 class="text-danger">
|
||||
|
@ -10,7 +10,7 @@
|
||||
<li class="nav-item" permission="@Policies.CanModifyStoreSettings">
|
||||
<a asp-area="" asp-controller="UILNURL" asp-action="EditLightningAddress" asp-route-storeId="@store.Id" class="nav-link @ViewData.ActivePageClass("LightningAddress", nameof(StoreNavPages))" id="StoreNav-LightningAddress">
|
||||
<vc:icon symbol="nav-lightning-address "/>
|
||||
<span>Lightning Address</span>
|
||||
<span text-translate="true">Lightning Address</span>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
|
@ -53,8 +53,8 @@
|
||||
@if (ViewBag.ShowLeadText)
|
||||
{
|
||||
<p class="lead">
|
||||
<span class="d-sm-block">A self-hosted, open-source bitcoin payment processor.</span>
|
||||
<span class="d-sm-block">It is secure, private, censorship-resistant and free.</span>
|
||||
<span class="d-sm-block" text-translate="true">A self-hosted, open-source bitcoin payment processor.</span>
|
||||
<span class="d-sm-block" text-translate="true">It is secure, private, censorship-resistant and free.</span>
|
||||
</p>
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
@model CheatPermissionsViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Permissions";
|
||||
ViewData["Title"] = ViewLocalizer["Permissions"];
|
||||
Layout = "_LayoutSignedOut";
|
||||
}
|
||||
|
||||
@if (Model.StoreId is not null)
|
||||
{
|
||||
<h1>Store: @Model.StoreId</h1>
|
||||
<h1 text-translate="true">@ViewLocalizer["Store: {0}", @Model.StoreId]</h1>
|
||||
}
|
||||
else
|
||||
{
|
||||
<h1>No scope</h1>
|
||||
<h1 text-translate="true">No scope</h1>
|
||||
}
|
||||
|
||||
<ul>
|
||||
|
@ -1,7 +1,7 @@
|
||||
@model RegisterViewModel
|
||||
@inject BTCPayServer.Services.BTCPayServerEnvironment env
|
||||
@{
|
||||
ViewData["Title"] = "Create account";
|
||||
ViewData["Title"] = ViewLocalizer["Create account"];
|
||||
ViewBag.ShowLeadText = true;
|
||||
Layout = "_LayoutSignedOut";
|
||||
}
|
||||
@ -36,7 +36,7 @@
|
||||
</div>
|
||||
}
|
||||
<div class="form-group mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-lg w-100" id="RegisterButton">Create account</button>
|
||||
<button type="submit" class="btn btn-primary btn-lg w-100" id="RegisterButton" text-translate="true">Create account</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
@ -30,13 +30,13 @@
|
||||
<vc:icon symbol="warning" />
|
||||
</div>
|
||||
<div class="lead text-center">
|
||||
<h1 class="text-center text-warning mb-3">
|
||||
Secure your recovery phrase
|
||||
<h1 class="text-center text-warning mb-3" text-translate="true">
|
||||
Secure your recovery phrase
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lead text-center">
|
||||
<p class="mb-0">
|
||||
<p class="mb-0" text-translate="true">
|
||||
The combination of words below are called your recovery phrase.
|
||||
The recovery phrase allows you to access and restore your wallet.
|
||||
Write them down on a piece of paper in the exact order:
|
||||
@ -54,41 +54,41 @@
|
||||
@if (Model.IsStored)
|
||||
{
|
||||
<p>
|
||||
<span>The recovery phrase is a backup that allows you to restore your wallet in case of a server crash.</span>
|
||||
<span>If you lose it or write it down incorrectly, you may permanently lose access to your funds.</span>
|
||||
<span>Do not photograph it. Do not store it digitally.</span>
|
||||
<span text-translate="true">The recovery phrase is a backup that allows you to restore your wallet in case of a server crash.</span>
|
||||
<span text-translate="true">If you lose it or write it down incorrectly, you may permanently lose access to your funds.</span>
|
||||
<span text-translate="true">Do not photograph it. Do not store it digitally.</span>
|
||||
</p>
|
||||
<p class="text-warning">
|
||||
<strong>The recovery phrase will also be stored on the server as a hot wallet.</strong>
|
||||
<strong text-translate="true">The recovery phrase will also be stored on the server as a hot wallet.</strong>
|
||||
</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>
|
||||
<span>If you lose it or write it down incorrectly, you will permanently lose access to your funds.</span>
|
||||
<span>Do not photograph the recovery phrase, and do not store it digitally.</span>
|
||||
<span text-translate="true">If you lose it or write it down incorrectly, you will permanently lose access to your funds.</span>
|
||||
<span text-translate="true">Do not photograph the recovery phrase, and do not store it digitally.</span>
|
||||
</p>
|
||||
<br />
|
||||
<p class="text-warning">
|
||||
<strong>The recovery phrase will be permanently erased from the server.</strong>
|
||||
<strong text-translate="true">The recovery phrase will be permanently erased from the server.</strong>
|
||||
</p>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.Passphrase))
|
||||
{
|
||||
<p class="mt-3 mb-0">Please make sure to also write down your passphrase.</p>
|
||||
<p class="mt-3 mb-0" text-translate="true">Please make sure to also write down your passphrase.</p>
|
||||
}
|
||||
</div>
|
||||
@if (Model.RequireConfirm)
|
||||
{
|
||||
<form id="RecoveryConfirmation" action="@Url.EnsureLocal(Model.ReturnUrl, Context.Request)" class="position-relative d-flex align-items-start justify-content-center" style="padding:20px 0 100px" rel="noreferrer noopener">
|
||||
<label class="form-check-label lead order-2" for="confirm">I have written down my recovery phrase and stored it in a secure location</label>
|
||||
<label class="form-check-label lead order-2" for="confirm" text-translate="true">I have written down my recovery phrase and stored it in a secure location</label>
|
||||
<input type="checkbox" class="me-3 order-1 form-check-input" id="confirm" style="margin-top:.35rem;flex-shrink:0">
|
||||
<button type="submit" class="btn btn-primary btn-lg px-5 order-3" id="submit">Done</button>
|
||||
<button type="submit" class="btn btn-primary btn-lg px-5 order-3" disabled>Done</button>
|
||||
<button type="submit" class="btn btn-primary btn-lg px-5 order-3" id="submit" text-translate="true">Done</button>
|
||||
<button type="submit" class="btn btn-primary btn-lg px-5 order-3" disabled text-translate="true">Done</button>
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a href="@Url.EnsureLocal(Model.ReturnUrl, Context.Request)" class="btn btn-primary btn-lg mt-3 px-5 order-3" id="proceed" rel="noreferrer noopener">Done</a>
|
||||
<a href="@Url.EnsureLocal(Model.ReturnUrl, Context.Request)" class="btn btn-primary btn-lg mt-3 px-5 order-3" id="proceed" rel="noreferrer noopener" text-translate="true">Done</a>
|
||||
}
|
||||
</main>
|
||||
|
@ -1,6 +1,6 @@
|
||||
@model BTCPayServer.Models.NotificationViewModels.NotificationIndexViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Notifications";
|
||||
ViewData["Title"] = ViewLocalizer["Notifications"];
|
||||
string status = ViewBag.Status;
|
||||
var statusFilterCount = CountArrayFilter("type");
|
||||
var storesFilterCount = CountArrayFilter("storeid");
|
||||
|
@ -6,7 +6,7 @@
|
||||
@model BTCPayServer.Models.PaymentRequestViewModels.ListPaymentRequestsViewModel
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["Title"] = "Payment Requests";
|
||||
ViewData["Title"] = ViewLocalizer["Payment Requests"];
|
||||
var storeId = Context.GetStoreData().Id;
|
||||
var statusFilterCount = CountArrayFilter("status") + (HasBooleanFilter("includearchived") ? 1 : 0);
|
||||
}
|
||||
|
@ -9,8 +9,8 @@
|
||||
@using BTCPayServer.Client
|
||||
@model StoreDashboardViewModel
|
||||
@{
|
||||
BTCPayServer.Plugins.PluginExceptionHandler.SetDisablePluginIfCrash(Context);
|
||||
ViewData.SetActivePage(StoreNavPages.Dashboard, Model.StoreName, Model.StoreId);
|
||||
BTCPayServer.Plugins.PluginExceptionHandler.SetDisablePluginIfCrash(Context);
|
||||
ViewData.SetActivePage(StoreNavPages.Dashboard, Model.StoreName, Model.StoreId);
|
||||
var store = ViewContext.HttpContext.GetStoreData();
|
||||
}
|
||||
|
||||
@ -50,61 +50,61 @@
|
||||
};
|
||||
</script>
|
||||
<div id="Dashboard" class="mt-4">
|
||||
<vc:ui-extension-point location="dashboard" model="@Model"/>
|
||||
<vc:ui-extension-point location="dashboard" model="@Model" />
|
||||
@if (Model.WalletEnabled)
|
||||
{
|
||||
<vc:store-wallet-balance store="@store"/>
|
||||
<vc:store-wallet-balance store="@store" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="widget setup-guide">
|
||||
<header>
|
||||
<h5 class="mb-4 text-muted">This store is ready to accept transactions, good job!</h5>
|
||||
<h5 class="mb-4 text-muted" text-translate="true">This store is ready to accept transactions, good job!</h5>
|
||||
</header>
|
||||
<div class="list-group" id="SetupGuide">
|
||||
<div class="list-group-item d-flex align-items-center" id="SetupGuide-LightningDone">
|
||||
<vc:icon symbol="done"/>
|
||||
<vc:icon symbol="done" />
|
||||
<div class="content">
|
||||
<h5 class="mb-0 text-success">Set up a Lightning node</h5>
|
||||
<h5 class="mb-0 text-success" text-translate="true">Set up a Lightning node</h5>
|
||||
</div>
|
||||
</div>
|
||||
<a asp-controller="UIStores" asp-action="SetupWallet" asp-route-storeId="@Model.StoreId" asp-route-cryptoCode="@Model.CryptoCode" id="SetupGuide-Wallet" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<vc:icon symbol="wallet-new"/>
|
||||
<vc:icon symbol="wallet-new" />
|
||||
<div class="content">
|
||||
<h5 class="mb-0">Set up a wallet</h5>
|
||||
<h5 class="mb-0" text-translate="true">Set up a wallet</h5>
|
||||
</div>
|
||||
<vc:icon symbol="caret-right"/>
|
||||
<vc:icon symbol="caret-right" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<vc:store-numbers vm="@(new StoreNumbersViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })"/>
|
||||
<vc:store-numbers vm="@(new StoreNumbersViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })" />
|
||||
@if (Model.LightningEnabled)
|
||||
{
|
||||
<vc:store-lightning-balance vm="@(new StoreLightningBalanceViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })"/>
|
||||
<vc:store-lightning-services vm="@(new StoreLightningServicesViewModel { Store = store, CryptoCode = Model.CryptoCode })" permission="@Policies.CanModifyServerSettings"/>
|
||||
<vc:store-lightning-balance vm="@(new StoreLightningBalanceViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })" />
|
||||
<vc:store-lightning-services vm="@(new StoreLightningServicesViewModel { Store = store, CryptoCode = Model.CryptoCode })" permission="@Policies.CanModifyServerSettings" />
|
||||
}
|
||||
@if (Model.WalletEnabled)
|
||||
{
|
||||
<vc:store-recent-transactions vm="@(new StoreRecentTransactionsViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })"/>
|
||||
<vc:store-recent-transactions vm="@(new StoreRecentTransactionsViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })" />
|
||||
}
|
||||
<vc:store-recent-invoices vm="@(new StoreRecentInvoicesViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })"/>
|
||||
<vc:store-recent-invoices vm="@(new StoreRecentInvoicesViewModel { Store = store, CryptoCode = Model.CryptoCode, InitialRendering = true })" />
|
||||
@foreach (var app in Model.Apps)
|
||||
{
|
||||
<vc:app-sales app-id="@app.Id" app-type="@app.AppType" />
|
||||
<vc:app-top-items app-id="@app.Id" app-type="@app.AppType" />
|
||||
<vc:app-sales app-id="@app.Id" app-type="@app.AppType" />
|
||||
<vc:app-top-items app-id="@app.Id" app-type="@app.AppType" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="lead text-secondary mt-2">To start accepting payments, set up a wallet or a Lightning node.</p>
|
||||
|
||||
<p class="lead text-secondary mt-2" text-translate="true">To start accepting payments, set up a wallet or a Lightning node.</p>
|
||||
|
||||
<div class="list-group" id="SetupGuide">
|
||||
<div class="list-group-item d-flex align-items-center" id="SetupGuide-StoreDone">
|
||||
<vc:icon symbol="done"/>
|
||||
<vc:icon symbol="done" />
|
||||
<div class="content">
|
||||
<h5 class="mb-0 text-success">Create your store</h5>
|
||||
<h5 class="mb-0 text-success" text-translate="true">Create your store</h5>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.Network is BTCPayNetwork)
|
||||
@ -113,40 +113,41 @@ else
|
||||
@if (!Model.WalletEnabled)
|
||||
{
|
||||
<a asp-controller="UIStores" asp-action="SetupWallet" asp-route-storeId="@Model.StoreId" asp-route-cryptoCode="@Model.CryptoCode" id="SetupGuide-Wallet" class="list-group-item list-group-item-action d-flex align-items-center order-1">
|
||||
<vc:icon symbol="wallet-new"/>
|
||||
<vc:icon symbol="wallet-new" />
|
||||
<div class="content">
|
||||
<h5 class="mb-0">Set up a wallet</h5>
|
||||
<h5 class="mb-0" text-translate="true">Set up a wallet</h5>
|
||||
</div>
|
||||
<vc:icon symbol="caret-right"/>
|
||||
<vc:icon symbol="caret-right" />
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="list-group-item d-flex align-items-center" id="SetupGuide-WalletDone">
|
||||
<vc:icon symbol="done"/>
|
||||
<vc:icon symbol="done" />
|
||||
<div class="content">
|
||||
<h5 class="mb-0 text-success">Set up a wallet</h5>
|
||||
<h5 class="mb-0 text-success" text-translate="true">Set up a wallet</h5>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (Model.LightningSupported) {
|
||||
@if (Model.LightningSupported)
|
||||
{
|
||||
if (!Model.LightningEnabled)
|
||||
{
|
||||
<a asp-controller="UIStores" asp-action="SetupLightningNode" asp-route-storeId="@Model.StoreId" asp-route-cryptoCode="@Model.CryptoCode" id="SetupGuide-Lightning" class="list-group-item list-group-item-action d-flex align-items-center order-1">
|
||||
<vc:icon symbol="wallet-new"/>
|
||||
<vc:icon symbol="wallet-new" />
|
||||
<div class="content">
|
||||
<h5 class="mb-0">Set up a Lightning node</h5>
|
||||
<h5 class="mb-0" text-translate="true">Set up a Lightning node</h5>
|
||||
</div>
|
||||
<vc:icon symbol="caret-right"/>
|
||||
<vc:icon symbol="caret-right" />
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="list-group-item d-flex align-items-center" id="SetupGuide-LightningDone">
|
||||
<vc:icon symbol="done"/>
|
||||
<vc:icon symbol="done" />
|
||||
<div class="content">
|
||||
<h5 class="mb-0 text-success">Set up a Lightning node</h5>
|
||||
<h5 class="mb-0 text-success" text-translate="true">Set up a Lightning node</h5>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
@model LightningNodeViewModel
|
||||
@{
|
||||
Layout = "_LayoutWalletSetup.cshtml";
|
||||
ViewData.SetActivePage(StoreNavPages.LightningSettings, "Connect to a Lightning node", Context.GetStoreData().Id);
|
||||
ViewData.SetActivePage(StoreNavPages.LightningSettings, StringLocalizer["Connect to a Lightning node"], Context.GetStoreData().Id);
|
||||
}
|
||||
|
||||
@section PageHeadContent {
|
||||
@ -28,10 +28,10 @@
|
||||
<form method="post" class="mt-n2 text-center">
|
||||
<div id="LightningNodeTypeTablist" class="nav btcpay-pills align-items-center justify-content-center mb-3" role="tablist">
|
||||
<input asp-for="LightningNodeType" value="@LightningNodeType.Internal" type="radio" id="LightningNodeType-@LightningNodeType.Internal" data-bs-toggle="pill" data-bs-target="#InternalSetup" role="tab" aria-controls="InternalSetup" aria-selected="@(Model.LightningNodeType == LightningNodeType.Internal ? "true" : "false")" class="@(Model.LightningNodeType == LightningNodeType.Internal ? "active" : "")" disabled="@(!Model.CanUseInternalNode)">
|
||||
<label asp-for="LightningNodeType" for="@($"LightningNodeType-{LightningNodeType.Internal}")">Use internal node</label>
|
||||
<label asp-for="LightningNodeType" for="@($"LightningNodeType-{LightningNodeType.Internal}")" text-translate="true">Use internal node</label>
|
||||
|
||||
<input asp-for="LightningNodeType" value="@LightningNodeType.Custom" type="radio" id="LightningNodeType-@LightningNodeType.Custom" data-bs-toggle="pill" data-bs-target="#CustomSetup" role="tab" aria-controls="CustomSetup" aria-selected="@(Model.LightningNodeType == LightningNodeType.Custom ? "true" : "false")" class="@(Model.LightningNodeType == LightningNodeType.Custom ? "active" : "")">
|
||||
<label asp-for="LightningNodeType" for="@($"LightningNodeType-{LightningNodeType.Custom}")">Use custom node</label>
|
||||
<label asp-for="LightningNodeType" for="@($"LightningNodeType-{LightningNodeType.Custom}")" text-translate="true">Use custom node</label>
|
||||
|
||||
<vc:ui-extension-point location="ln-payment-method-setup-tabhead" model="@Model"/>
|
||||
</div>
|
||||
@ -40,24 +40,24 @@
|
||||
<div id="InternalSetup" class="pt-3 tab-pane fade @(Model.LightningNodeType == LightningNodeType.Internal ? "show active" : "")" role="tabpanel" aria-labelledby="LightningNodeType-@LightningNodeType.Internal">
|
||||
@if (Model.CanUseInternalNode)
|
||||
{
|
||||
<p class="mb-4">Using the BTCPay Server internal node for this store requires no further configuration. Click the save button below to start accepting Bitcoin through the Lightning Network.</p>
|
||||
<p class="mb-4" text-translate="true">Using the BTCPay Server internal node for this store requires no further configuration. Click the save button below to start accepting Bitcoin through the Lightning Network.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="mb-4">Your instance administrator has disabled the use of the Internal node for non-admin users.</p>
|
||||
<p class="mb-4" text-translate="true">Your instance administrator has disabled the use of the Internal node for non-admin users.</p>
|
||||
}
|
||||
</div>
|
||||
<div id="CustomSetup" class="pt-3 tab-pane fade @(Model.LightningNodeType == LightningNodeType.Custom ? "show active" : "")" role="tabpanel" aria-labelledby="LightningNodeType-@LightningNodeType.Custom">
|
||||
<div class="form-group">
|
||||
<label asp-for="ConnectionString" class="form-label">Connection configuration for your custom Lightning node:</label>
|
||||
<label asp-for="ConnectionString" class="form-label" text-translate="true">Connection configuration for your custom Lightning node:</label>
|
||||
<div class="d-sm-flex">
|
||||
<input asp-for="ConnectionString" class="form-control mb-2 me-2" placeholder="type=…;server=…;" value="@(Model.LightningNodeType == LightningNodeType.Internal ? "" : Model.ConnectionString)"/>
|
||||
<button id="test" name="command" type="submit" value="test" class="btn btn-secondary text-nowrap mb-2">Test connection</button>
|
||||
<button id="test" name="command" type="submit" value="test" class="btn btn-secondary text-nowrap mb-2" text-translate="true">Test connection</button>
|
||||
</div>
|
||||
<span asp-validation-for="ConnectionString" class="text-danger"></span>
|
||||
</div>
|
||||
<vc:ui-extension-point location="ln-payment-method-setup-custom" model="@Model"/>
|
||||
<p class="mt-4 mb-2">BTCPay Server currently supports:</p>
|
||||
<p class="mt-4 mb-2" text-translate="true">BTCPay Server currently supports:</p>
|
||||
<div class="accordion" id="CustomNodeSupport">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="CustomNodeCLightningHeader">
|
||||
|
@ -18,7 +18,7 @@
|
||||
<div class="form-group">
|
||||
<label asp-for="PreferredExchange" class="form-label" data-required></label>
|
||||
<select asp-for="PreferredExchange" asp-items="Model.Exchanges" class="form-select w-300px"></select>
|
||||
<div class="form-text mt-2 only-for-js">The recommended price source gets chosen based on the default currency.</div>
|
||||
<div class="form-text mt-2 only-for-js" text-translate="true">The recommended price source gets chosen based on the default currency.</div>
|
||||
<span asp-validation-for="PreferredExchange" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group mt-4">
|
||||
|
@ -11,6 +11,7 @@
|
||||
@using Microsoft.AspNetCore.Routing;
|
||||
@using BTCPayServer.Abstractions.Extensions;
|
||||
@inject Microsoft.AspNetCore.Mvc.Localization.ViewLocalizer ViewLocalizer
|
||||
@inject Microsoft.Extensions.Localization.IStringLocalizer StringLocalizer
|
||||
@inject Safe Safe
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@addTagHelper *, BTCPayServer
|
||||
|
Loading…
Reference in New Issue
Block a user