diff --git a/src/Machine/src/Serval.Machine.Shared/Serval.Machine.Shared.csproj b/src/Machine/src/Serval.Machine.Shared/Serval.Machine.Shared.csproj
index 4286a101..0d19202a 100644
--- a/src/Machine/src/Serval.Machine.Shared/Serval.Machine.Shared.csproj
+++ b/src/Machine/src/Serval.Machine.Shared/Serval.Machine.Shared.csproj
@@ -38,9 +38,9 @@
-
-
-
+
+
+
diff --git a/src/Serval/src/Serval.Shared/Serval.Shared.csproj b/src/Serval/src/Serval.Shared/Serval.Shared.csproj
index d26b72b9..a159d88a 100644
--- a/src/Serval/src/Serval.Shared/Serval.Shared.csproj
+++ b/src/Serval/src/Serval.Shared/Serval.Shared.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/src/Serval/src/Serval.Translation/Services/PretranslationService.cs b/src/Serval/src/Serval.Translation/Services/PretranslationService.cs
index 72a2c65e..aa4c3c79 100644
--- a/src/Serval/src/Serval.Translation/Services/PretranslationService.cs
+++ b/src/Serval/src/Serval.Translation/Services/PretranslationService.cs
@@ -320,26 +320,44 @@ private static string DenormalizeQuotationMarks(string usfm, ParallelCorpusAnaly
QuotationMarkDenormalizationFirstPass quotationMarkDenormalizationFirstPass = new(targetQuoteConvention);
UsfmParser.Parse(usfm, quotationMarkDenormalizationFirstPass);
- List bestChapterStrategies =
+ List<(int ChapterNumber, QuotationMarkUpdateStrategy Strategy)> bestChapterStrategies =
quotationMarkDenormalizationFirstPass.FindBestChapterStrategies();
QuotationMarkDenormalizationUsfmUpdateBlockHandler quotationMarkDenormalizer =
- new(targetQuoteConvention, new QuotationMarkUpdateSettings(chapterStrategies: bestChapterStrategies));
+ new(
+ targetQuoteConvention,
+ new QuotationMarkUpdateSettings(
+ chapterStrategies: bestChapterStrategies.Select(tuple => tuple.Strategy).ToList()
+ )
+ );
+ int denormalizableChapterCount = bestChapterStrategies.Count(tup =>
+ tup.Strategy != QuotationMarkUpdateStrategy.Skip
+ );
List remarks = [];
- if (bestChapterStrategies.Any(s => s != QuotationMarkUpdateStrategy.Skip))
+ string quotationDenormalizationRemark;
+ if (denormalizableChapterCount == bestChapterStrategies.Count)
{
- string quotationDenormalizationRemark =
+ quotationDenormalizationRemark =
+ "The quote style in all chapters has been automatically adjusted to match the rest of the project.";
+ }
+ else if (denormalizableChapterCount > 0)
+ {
+ quotationDenormalizationRemark =
"The quote style in the following chapters has been automatically adjusted to match the rest of the project: "
- + string.Join(
- ", ",
+ + GetChapterRangesString(
bestChapterStrategies
- .Select((strategy, index) => (strategy, index))
- .Where(tuple => tuple.strategy != QuotationMarkUpdateStrategy.Skip)
- .Select(tuple => tuple.index + 1)
+ .Where(tuple => tuple.Strategy != QuotationMarkUpdateStrategy.Skip)
+ .Select(tuple => tuple.ChapterNumber)
+ .ToList()
)
+ ".";
- remarks.Add(quotationDenormalizationRemark);
}
+ else
+ {
+ quotationDenormalizationRemark =
+ "The quote style was not automatically adjusted to match the rest of your project in any chapters.";
+ }
+ remarks.Add(quotationDenormalizationRemark);
var updater = new UpdateUsfmParserHandler(updateBlockHandlers: [quotationMarkDenormalizer], remarks: remarks);
UsfmParser.Parse(usfm, updater);
@@ -348,6 +366,43 @@ private static string DenormalizeQuotationMarks(string usfm, ParallelCorpusAnaly
return usfm;
}
+ public static string GetChapterRangesString(List chapterNumbers)
+ {
+ chapterNumbers = chapterNumbers.Order().ToList();
+ int start = chapterNumbers[0];
+ int end = chapterNumbers[0];
+ List chapterRangeStrings = [];
+ foreach (int chapterNumber in chapterNumbers[1..])
+ {
+ if (chapterNumber == end + 1)
+ {
+ end = chapterNumber;
+ }
+ else
+ {
+ if (start == end)
+ {
+ chapterRangeStrings.Add(start.ToString(CultureInfo.InvariantCulture));
+ }
+ else
+ {
+ chapterRangeStrings.Add($"{start}-{end}");
+ }
+ start = chapterNumber;
+ end = chapterNumber;
+ }
+ }
+ if (start == end)
+ {
+ chapterRangeStrings.Add(start.ToString(CultureInfo.InvariantCulture));
+ }
+ else
+ {
+ chapterRangeStrings.Add($"{start}-{end}");
+ }
+ return string.Join(", ", chapterRangeStrings);
+ }
+
///
/// Generate a natural sounding remark/comment describing marker placement.
///
diff --git a/src/Serval/test/Serval.Translation.Tests/Services/PretranslationServiceTests.cs b/src/Serval/test/Serval.Translation.Tests/Services/PretranslationServiceTests.cs
index f6f42bdc..d6f950f8 100644
--- a/src/Serval/test/Serval.Translation.Tests/Services/PretranslationServiceTests.cs
+++ b/src/Serval/test/Serval.Translation.Tests/Services/PretranslationServiceTests.cs
@@ -425,6 +425,18 @@ public void GetUsfmAsync_BadPretranslationVerseRef()
});
}
+ [Test]
+ [TestCase(new int[] { 1, 2, 3 }, "1-3")]
+ [TestCase(new int[] { 1, 3, 4 }, "1, 3-4")]
+ [TestCase(new int[] { 2, 3, 4, 6, 8, 9 }, "2-4, 6, 8-9")]
+ [TestCase(new int[] { 1, 3, 2 }, "1-3")]
+ [TestCase(new int[] { 1 }, "1")]
+ public void GetChapterRanges(int[] chapterNumbers, string expectedRangeString)
+ {
+ string actualRangeString = PretranslationService.GetChapterRangesString(chapterNumbers.ToList());
+ Assert.That(actualRangeString, Is.EqualTo(expectedRangeString));
+ }
+
private class TestEnvironment : IDisposable
{
public TestEnvironment()
diff --git a/src/ServiceToolkit/src/SIL.ServiceToolkit/SIL.ServiceToolkit.csproj b/src/ServiceToolkit/src/SIL.ServiceToolkit/SIL.ServiceToolkit.csproj
index 13691c33..4054de0b 100644
--- a/src/ServiceToolkit/src/SIL.ServiceToolkit/SIL.ServiceToolkit.csproj
+++ b/src/ServiceToolkit/src/SIL.ServiceToolkit/SIL.ServiceToolkit.csproj
@@ -18,7 +18,7 @@
-
+