mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 14:04:26 +01:00
feat : add functionality to download language pack (#6943)
* refactor : added link to translations files Signed-off-by: Abhijay007 <Abhijay007j@gmail.com> * feat : added ability to download langauge pack Signed-off-by: Abhijay007 <Abhijay007j@gmail.com> * refactor: removed link for the edit page Signed-off-by: Abhijay007 <Abhijay007j@gmail.com> * refactor: server-side downloading instead of JavaScript Signed-off-by: Abhijay007 <Abhijay007j@gmail.com> * refactor : addressed request changes Signed-off-by: Abhijay007 <Abhijay007j@gmail.com> * refactor: updated GetDictionary method and other changes Signed-off-by: Abhijay007 <Abhijay007j@gmail.com> --------- Signed-off-by: Abhijay007 <Abhijay007j@gmail.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
|
using System;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Models.ServerViewModels;
|
using BTCPayServer.Models.ServerViewModels;
|
||||||
@@ -122,5 +124,53 @@ namespace BTCPayServer.Controllers
|
|||||||
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Dictionary {0} deleted", dictionary].Value;
|
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Dictionary {0} deleted", dictionary].Value;
|
||||||
return RedirectToAction(nameof(ListDictionaries));
|
return RedirectToAction(nameof(ListDictionaries));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("server/dictionaries/download")]
|
||||||
|
public async Task<IActionResult> DownloadLanguagePack(string language)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(language))
|
||||||
|
{
|
||||||
|
TempData[WellKnownTempData.ErrorMessage] = StringLocalizer["Please select a language"].Value;
|
||||||
|
return RedirectToAction(nameof(ListDictionaries));
|
||||||
|
}
|
||||||
|
|
||||||
|
string translationsJson;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
translationsJson = await FetchLanguagePackFromRepository(language);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
TempData[WellKnownTempData.ErrorMessage] = StringLocalizer["Failed to download language pack: {0}", ex.Message].Value;
|
||||||
|
return RedirectToAction(nameof(ListDictionaries));
|
||||||
|
}
|
||||||
|
|
||||||
|
var translations = Translations.CreateFromJson(translationsJson);
|
||||||
|
var existingDictionary = await _localizer.GetDictionary(language);
|
||||||
|
if (existingDictionary is null)
|
||||||
|
{
|
||||||
|
existingDictionary = await _localizer.CreateDictionary(language, Translations.DefaultLanguage, "Custom");
|
||||||
|
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Language pack '{0}' downloaded successfully", language].Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TempData[WellKnownTempData.SuccessMessage] = StringLocalizer["Language pack '{0}' updated successfully", language].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _localizer.Save(existingDictionary, translations);
|
||||||
|
return RedirectToAction(nameof(ListDictionaries));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> FetchLanguagePackFromRepository(string language)
|
||||||
|
{
|
||||||
|
var fileName = language.ToLowerInvariant();
|
||||||
|
var url = $"https://raw.githubusercontent.com/btcpayserver/btcpayserver-translator/main/translations/{fileName}.json";
|
||||||
|
|
||||||
|
var httpClient = HttpClientFactory.CreateClient();
|
||||||
|
using var response = await httpClient.GetAsync(url);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ namespace BTCPayServer.Services
|
|||||||
{
|
{
|
||||||
await using var ctx = _ContextFactory.CreateContext();
|
await using var ctx = _ContextFactory.CreateContext();
|
||||||
var db = ctx.Database.GetDbConnection();
|
var db = ctx.Database.GetDbConnection();
|
||||||
var r = await db.QueryFirstAsync("SELECT * FROM lang_dictionaries WHERE dict_id=@dict_id", new { dict_id = name });
|
var r = await db.QueryFirstOrDefaultAsync("SELECT * FROM lang_dictionaries WHERE dict_id=@dict_id", new { dict_id = name });
|
||||||
if (r is null)
|
if (r is null)
|
||||||
return null;
|
return null;
|
||||||
return new Dictionary(r.dict_id, r.fallback, r.source ?? "", JObject.Parse(r.metadata ?? "{}"));
|
return new Dictionary(r.dict_id, r.fallback, r.source ?? "", JObject.Parse(r.metadata ?? "{}"));
|
||||||
|
|||||||
@@ -6,10 +6,15 @@
|
|||||||
|
|
||||||
<div class="sticky-header">
|
<div class="sticky-header">
|
||||||
<h2>@ViewData["Title"]</h2>
|
<h2>@ViewData["Title"]</h2>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#downloadLanguagePackModal" text-translate="true">
|
||||||
|
Download language pack
|
||||||
|
</button>
|
||||||
<a id="page-primary" asp-action="CreateDictionary" class="btn btn-primary" role="button">
|
<a id="page-primary" asp-action="CreateDictionary" class="btn btn-primary" role="button">
|
||||||
Create
|
Create
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<partial name="_StatusMessage" />
|
<partial name="_StatusMessage" />
|
||||||
|
|
||||||
<p class="mb-0" text-translate="true">
|
<p class="mb-0" text-translate="true">
|
||||||
@@ -65,3 +70,50 @@
|
|||||||
</table>
|
</table>
|
||||||
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Delete dictionary"], StringLocalizer["This dictionary will be removed from this server."], StringLocalizer["Delete"]))" />
|
<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Delete dictionary"], StringLocalizer["This dictionary will be removed from this server."], StringLocalizer["Delete"]))" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@* Download Language Pack Modal *@
|
||||||
|
<div class="modal fade" id="downloadLanguagePackModal" tabindex="-1" role="dialog" aria-labelledby="downloadLanguagePackModalTitle" aria-hidden="true" data-bs-backdrop="static">
|
||||||
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
|
<form method="post" asp-action="DownloadLanguagePack">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="downloadLanguagePackModalTitle" text-translate="true">Download Language Pack</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||||
|
<vc:icon symbol="close" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p text-translate="true">Select a language to download from the community translation repository.</p>
|
||||||
|
<p class="mb-3">
|
||||||
|
<span text-translate="true">These translations are maintained by the community at</span>
|
||||||
|
<a href="https://github.com/btcpayserver/btcpayserver-translator" target="_blank" rel="noopener noreferrer">btcpayserver-translator</a>.
|
||||||
|
</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="language" class="form-label" text-translate="true">Select Language</label>
|
||||||
|
<select id="language" name="language" class="form-select" required>
|
||||||
|
<option value="" text-translate="true">Choose a language...</option>
|
||||||
|
<option value="Dutch">Dutch</option>
|
||||||
|
<option value="French">French</option>
|
||||||
|
<option value="German">German</option>
|
||||||
|
<option value="Hindi">Hindi</option>
|
||||||
|
<option value="Indonesian">Indonesian</option>
|
||||||
|
<option value="Italian">Italian</option>
|
||||||
|
<option value="Japanese">Japanese</option>
|
||||||
|
<option value="Korean">Korean</option>
|
||||||
|
<option value="Portuguese (Brazil)">Portuguese (Brazil)</option>
|
||||||
|
<option value="Russian">Russian</option>
|
||||||
|
<option value="Serbian">Serbian</option>
|
||||||
|
<option value="Spanish">Spanish</option>
|
||||||
|
<option value="Thai">Thai</option>
|
||||||
|
<option value="Turkish">Turkish</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" text-translate="true">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-primary" text-translate="true">Download</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user