tajik + persian text backend
This commit is contained in:
parent
061853a365
commit
978c6f6e0e
@ -8,7 +8,6 @@ using Newtonsoft.Json;
|
||||
using RMuseum.Models.Auth.Memory;
|
||||
using RMuseum.Models.Auth.ViewModel;
|
||||
using RMuseum.Models.Ganjoor;
|
||||
using RMuseum.Models.Ganjoor.PublicExport;
|
||||
using RMuseum.Models.Ganjoor.ViewModels;
|
||||
using RMuseum.Models.GanjoorAudio.ViewModels;
|
||||
using RMuseum.Models.GanjoorIntegration;
|
||||
@ -2424,81 +2423,6 @@ namespace RMuseum.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// start exporting all published Ganjoor data to the public git-tracked JSON data set
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("publicdata/batchexport")]
|
||||
[Authorize(Policy = RMuseumSecurableItem.GanjoorEntityShortName + ":" + RMuseumSecurableItem.ImportOperationShortName)]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
|
||||
public IActionResult StartBatchExportPublicGitData()
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = _ganjoorService.StartBatchExportPublicGitData();
|
||||
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||
return BadRequest(res.ExceptionString);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
return BadRequest(exp.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// start exporting the Tajik (Cyrillic) overlay data to its own, separate public
|
||||
/// git-tracked JSON data set — only poets/categories/poems with an actual Tajik
|
||||
/// translation are included
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("tajik/publicdata/batchexport")]
|
||||
[Authorize(Policy = RMuseumSecurableItem.GanjoorEntityShortName + ":" + RMuseumSecurableItem.ImportOperationShortName)]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
|
||||
public IActionResult StartBatchExportTajikPublicGitData()
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = _ganjoorService.StartBatchExportTajikPublicGitData();
|
||||
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||
return BadRequest(res.ExceptionString);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
return BadRequest(exp.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (re)build local Ganjoor content from a public data export tree (local folder or HTTP) —
|
||||
/// intended for local development use, not for production servers
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("publicdata/import")]
|
||||
[Authorize(Policy = RMuseumSecurableItem.GanjoorEntityShortName + ":" + RMuseumSecurableItem.ImportOperationShortName)]
|
||||
[ProducesResponseType((int)HttpStatusCode.OK)]
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
|
||||
public IActionResult StartImportFromPublicDataRepo([FromBody] PublicDataImportRequestDto request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = _ganjoorService.StartImportFromPublicDataRepo(request.UseHttp, request.Location, request.PoetId);
|
||||
if (!string.IsNullOrEmpty(res.ExceptionString))
|
||||
return BadRequest(res.ExceptionString);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
return BadRequest(exp.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get user public profile
|
||||
/// </summary>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
namespace RMuseum.Models.Ganjoor.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
{ /// <summary>
|
||||
/// Ganjoor Verse View Model
|
||||
/// </summary>
|
||||
public class GanjoorVerseViewModel
|
||||
@ -60,6 +59,13 @@
|
||||
/// </summary>
|
||||
public string CoupletSummary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// original (Persian) text - only populated for Tajik responses that need to show
|
||||
/// the Persian original alongside the Tajik transliteration. This is a pure view
|
||||
/// model (not an EF entity), so no [NotMapped] or migration concerns here.
|
||||
/// </summary>
|
||||
public string OriginalText { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Text;
|
||||
|
||||
@ -1775,27 +1775,6 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.GanjoorController.StartBatchExportPublicGitData">
|
||||
<summary>
|
||||
start exporting all published Ganjoor data to the public git-tracked JSON data set
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.GanjoorController.StartBatchExportTajikPublicGitData">
|
||||
<summary>
|
||||
start exporting the Tajik (Cyrillic) overlay data to its own, separate public
|
||||
git-tracked JSON data set — only poets/categories/poems with an actual Tajik
|
||||
translation are included
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.GanjoorController.StartImportFromPublicDataRepo(RMuseum.Models.Ganjoor.PublicExport.PublicDataImportRequestDto)">
|
||||
<summary>
|
||||
(re)build local Ganjoor content from a public data export tree (local folder or HTTP) —
|
||||
intended for local development use, not for production servers
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.GanjoorController.GetUserPublicProfile(System.Guid)">
|
||||
<summary>
|
||||
Get user public profile
|
||||
@ -13590,6 +13569,13 @@
|
||||
couplet summary
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:RMuseum.Models.Ganjoor.ViewModels.GanjoorVerseViewModel.OriginalText">
|
||||
<summary>
|
||||
original (Persian) text - only populated for Tajik responses that need to show
|
||||
the Persian original alongside the Tajik transliteration. This is a pure view
|
||||
model (not an EF entity), so no [NotMapped] or migration concerns here.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RMuseum.Models.Ganjoor.ViewModels.PoemMusicTrackViewModel">
|
||||
<summary>
|
||||
Ganjoor Poem related music track model
|
||||
@ -17537,31 +17523,6 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.IGanjoorService.StartBatchExportPublicGitData">
|
||||
<summary>
|
||||
start exporting all published data (poets/categories/poems/verses) to the public
|
||||
git-tracked JSON data set, committing and pushing changes since the last run
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.IGanjoorService.StartBatchExportTajikPublicGitData">
|
||||
<summary>
|
||||
start exporting the Tajik (Cyrillic) overlay data to its own separate git-tracked JSON
|
||||
data set — only entities that actually have a Tajik translation are included
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.IGanjoorService.StartImportFromPublicDataRepo(System.Boolean,System.String,System.Int32)">
|
||||
<summary>
|
||||
(re)build local Ganjoor content (poets/categories/poems/verses/sections + their pages)
|
||||
from a public data export tree, read locally or over HTTP. Safe to re-run — existing
|
||||
entities (by id) are left untouched, only missing ones are added.
|
||||
</summary>
|
||||
<param name="useHttp">true: fetch over HTTP (location is a base URL). false: read from a local folder (location is a path).</param>
|
||||
<param name="location">base URL or local folder path of the exported data tree</param>
|
||||
<param name="poetId">0 imports every poet; a specific id imports only that poet (useful on a slow connection)</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.IGanjoorService.HealthCheckContents">
|
||||
<summary>
|
||||
examine site pages for broken links
|
||||
@ -21657,6 +21618,16 @@
|
||||
short plain-text excerpt (first non-empty line) for a Tajik poem's next/previous nav link
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.Implementation.GanjoorService.PrepareBilingualHtmlText(RMuseum.Models.Ganjoor.ViewModels.GanjoorVerseViewModel[])">
|
||||
<summary>
|
||||
Tajik counterpart of PrepareHtmlText (GanjoorService-SQLiteImport.cs) - same
|
||||
VersePosition-based structure/CSS classes, but each verse's Persian original
|
||||
(GanjoorVerse.OriginalText, set just before this is called) is rendered as an
|
||||
extra <p class="tg-fa" dir="rtl"> line directly under its Tajik line, for
|
||||
an interlinear/bilingual display. Computed fresh per-request rather than stored,
|
||||
since it's cheap given the verses are already loaded for the response.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:RMuseum.Services.Implementation.GanjoorService.RegenerateTajikCatAndPoetHtmlTextAsync">
|
||||
<summary>
|
||||
re-runs the Tajik poet/category HTML generators for every already-imported poet and
|
||||
|
||||
@ -633,31 +633,6 @@ namespace RMuseum.Services
|
||||
/// <returns></returns>
|
||||
RServiceResult<bool> StartBatchGenerateGDBFiles();
|
||||
|
||||
/// <summary>
|
||||
/// start exporting all published data (poets/categories/poems/verses) to the public
|
||||
/// git-tracked JSON data set, committing and pushing changes since the last run
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
RServiceResult<bool> StartBatchExportPublicGitData();
|
||||
|
||||
/// <summary>
|
||||
/// start exporting the Tajik (Cyrillic) overlay data to its own separate git-tracked JSON
|
||||
/// data set — only entities that actually have a Tajik translation are included
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
RServiceResult<bool> StartBatchExportTajikPublicGitData();
|
||||
|
||||
/// <summary>
|
||||
/// (re)build local Ganjoor content (poets/categories/poems/verses/sections + their pages)
|
||||
/// from a public data export tree, read locally or over HTTP. Safe to re-run — existing
|
||||
/// entities (by id) are left untouched, only missing ones are added.
|
||||
/// </summary>
|
||||
/// <param name="useHttp">true: fetch over HTTP (location is a base URL). false: read from a local folder (location is a path).</param>
|
||||
/// <param name="location">base URL or local folder path of the exported data tree</param>
|
||||
/// <param name="poetId">0 imports every poet; a specific id imports only that poet (useful on a slow connection)</param>
|
||||
/// <returns></returns>
|
||||
RServiceResult<bool> StartImportFromPublicDataRepo(bool useHttp, string location, int poetId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// examine site pages for broken links
|
||||
/// </summary>
|
||||
|
||||
@ -180,8 +180,13 @@ namespace RMuseum.Services.Implementation
|
||||
var tajikVerses = await _context.TajikVerses.AsNoTracking().Where(v => v.PoemId == page.Poem.Id).OrderBy(v => v.VOrder).ToListAsync();
|
||||
foreach( var verse in page.Poem.Verses)
|
||||
{
|
||||
verse.OriginalText = verse.Text;
|
||||
verse.Text = tajikVerses.Where(v => v.VOrder == verse.VOrder).Single().TajikText;
|
||||
}
|
||||
// recompute fresh on every request (verses are already in memory) rather than
|
||||
// relying on the precomputed TajikHtmlText blob - keeps this in sync with the
|
||||
// verse data automatically, no regeneration job needed if it ever changes again
|
||||
page.HtmlText = PrepareBilingualHtmlText(page.Poem.Verses);
|
||||
|
||||
if (page.Poem.Recitations != null)
|
||||
{
|
||||
@ -245,6 +250,101 @@ namespace RMuseum.Services.Implementation
|
||||
return firstLine.Length > 80 ? firstLine.Substring(0, 80) + "…" : firstLine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tajik counterpart of PrepareHtmlText (GanjoorService-SQLiteImport.cs) - same
|
||||
/// VersePosition-based structure/CSS classes, but each verse's Persian original
|
||||
/// (GanjoorVerse.OriginalText, set just before this is called) is rendered as an
|
||||
/// extra <p class="tg-fa" dir="rtl"> line directly under its Tajik line, for
|
||||
/// an interlinear/bilingual display. Computed fresh per-request rather than stored,
|
||||
/// since it's cheap given the verses are already loaded for the response.
|
||||
/// </summary>
|
||||
private static string PrepareBilingualHtmlText(GanjoorVerseViewModel[] verses)
|
||||
{
|
||||
string FaLine(string text) => string.IsNullOrEmpty(text) ? "" : $"<p class=\"tg-fa\" dir=\"rtl\">{text}</p>";
|
||||
|
||||
string htmlText = "";
|
||||
int coupletIndex = 0;
|
||||
for (int vIndex = 0; vIndex < verses.Length; vIndex++)
|
||||
{
|
||||
GanjoorVerseViewModel v = verses[vIndex];
|
||||
if (v.VersePosition == VersePosition.CenteredVerse1)
|
||||
{
|
||||
coupletIndex++;
|
||||
if (((vIndex + 1) < verses.Length) && (verses[vIndex + 1].VersePosition == VersePosition.CenteredVerse2))
|
||||
{
|
||||
htmlText += $"<div class=\"b2\" id=\"bn{coupletIndex}\"><p>{v.Text}</p>{FaLine(v.OriginalText)}{Environment.NewLine}";
|
||||
}
|
||||
else
|
||||
{
|
||||
htmlText += $"<div class=\"b2\" id=\"bn{coupletIndex}\"><p>{v.Text}</p>{FaLine(v.OriginalText)}</div>{Environment.NewLine}";
|
||||
}
|
||||
}
|
||||
else
|
||||
if (v.VersePosition == VersePosition.CenteredVerse2)
|
||||
{
|
||||
htmlText += $"<p>{v.Text}</p>{FaLine(v.OriginalText)}</div>{Environment.NewLine}";
|
||||
}
|
||||
else
|
||||
if (v.VersePosition == VersePosition.Right)
|
||||
{
|
||||
coupletIndex++;
|
||||
htmlText += $"<div class=\"b\" id=\"bn{coupletIndex}\"><div class=\"m1\"><p>{v.Text}</p>{FaLine(v.OriginalText)}</div>{Environment.NewLine}";
|
||||
}
|
||||
else
|
||||
if (v.VersePosition == VersePosition.Left)
|
||||
{
|
||||
htmlText += $"<div class=\"m2\"><p>{v.Text}</p>{FaLine(v.OriginalText)}</div></div>{Environment.NewLine}";
|
||||
}
|
||||
else
|
||||
if (v.VersePosition == VersePosition.Comment)
|
||||
{
|
||||
htmlText += $"<div class=\"c\"><p>{v.Text}</p>{FaLine(v.OriginalText)}</div>{Environment.NewLine}";
|
||||
}
|
||||
else
|
||||
if (v.VersePosition == VersePosition.Paragraph || v.VersePosition == VersePosition.Single)
|
||||
{
|
||||
coupletIndex++;
|
||||
string[] lines = v.Text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string[] faLines = string.IsNullOrEmpty(v.OriginalText) ? new string[0] : v.OriginalText.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
string cssClass = v.VersePosition == VersePosition.Paragraph ? "n" : "l";
|
||||
|
||||
if (lines.Length != 0)
|
||||
{
|
||||
if (v.Text.Length / lines.Length < 150)
|
||||
{
|
||||
htmlText += $"<div class=\"{cssClass}\" id=\"bn{coupletIndex}\"><p>{v.Text.Replace("\r\n", " ")}</p>{FaLine(v.OriginalText?.Replace("\r\n", " "))}</div>{Environment.NewLine}";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Persian original might not split into the exact same number of
|
||||
// lines as its Tajik translation - matched by index on a best-effort
|
||||
// basis; this branch only fires for long paragraph/note text, not the
|
||||
// actual poem verses (Right/Left/CenteredVerse), so a rare misalignment
|
||||
// here is a minor cosmetic issue, not a poem-text-accuracy one
|
||||
for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++)
|
||||
{
|
||||
string faOne = lineIndex < faLines.Length ? faLines[lineIndex] : "";
|
||||
htmlText += $"<div class=\"{cssClass}\" id=\"bn{coupletIndex}\"><p>{lines[lineIndex]}</p>{FaLine(faOne)}</div>{Environment.NewLine}";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(v.Text))
|
||||
{
|
||||
htmlText += $"<div class=\"{cssClass}\" id=\"bn{coupletIndex}\"><p> </p></div>{Environment.NewLine}";//empty line!
|
||||
}
|
||||
else
|
||||
{
|
||||
htmlText += $"<div class=\"{cssClass}\" id=\"bn{coupletIndex}\"><p>{v.Text}</p>{FaLine(v.OriginalText)}</div>{Environment.NewLine}";//not brave enough to ignore it!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return htmlText.Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// re-runs the Tajik poet/category HTML generators for every already-imported poet and
|
||||
/// category page, overwriting their stored TajikHtmlText. Needed one-time after changing
|
||||
|
||||
Loading…
Reference in New Issue
Block a user