diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html
index a6667c5496c..1e1dffbed40 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html
@@ -139,17 +139,23 @@
{{ t("confirm") }}
Training the language model
{{ t("confirm_training") }}
-
+
|
- {{ element.name }} |
+
+ {{ element.ranges.join(", ") }}
+ |
- {{ trainingSources[0].writingSystem.tag }} |
+
+ {{ this.i18n.getLanguageDisplayName(trainingSources[0].writingSystem.tag) }}
+ |
{{ element.source }} |
- {{ trainingTargets[0].writingSystem.tag }} |
+
+ {{ this.i18n.getLanguageDisplayName(trainingTargets[0].writingSystem.tag) }}
+ |
{{ element.target }} |
@@ -165,7 +171,7 @@
@for (book of userSelectedTranslateBooks; track book) {
- {{ book.name }}
+ {{ book.name }}
}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss
index 0a2a03d24d3..7a1ee8707fb 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss
@@ -104,7 +104,7 @@ app-notice {
padding-inline-start: 16px;
}
-.readonly-book {
+.confirm-book {
padding-block: 4px;
font-weight: 500;
}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts
index 4a80596b4f2..d1ebb7a98b6 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts
@@ -10,6 +10,7 @@ import { Subscription, merge } from 'rxjs';
import { filter, tap } from 'rxjs/operators';
import { ActivatedProjectService } from 'xforge-common/activated-project.service';
import { FeatureFlagService } from 'xforge-common/feature-flags/feature-flag.service';
+import { I18nService } from 'xforge-common/i18n.service';
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
import { SubscriptionDisposable } from 'xforge-common/subscription-disposable';
import { UICommonModule } from 'xforge-common/ui-common.module';
@@ -38,7 +39,13 @@ export interface Book {
number: number;
}
-export interface TrainingBook extends Book {
+export interface TrainingBook extends Book, TrainingPair {}
+
+export interface TrainingGroup extends TrainingPair {
+ ranges: string[];
+}
+
+interface TrainingPair {
source: string;
target: string;
}
@@ -102,10 +109,11 @@ export class DraftGenerationStepsComponent extends SubscriptionDisposable implem
constructor(
private readonly activatedProject: ActivatedProjectService,
private readonly draftSourcesService: DraftSourcesService,
- readonly featureFlags: FeatureFlagService,
+ protected readonly featureFlags: FeatureFlagService,
private readonly nllbLanguageService: NllbLanguageService,
private readonly trainingDataService: TrainingDataService,
- private readonly progressService: ProgressService
+ private readonly progressService: ProgressService,
+ protected readonly i18n: I18nService
) {
super();
const project = activatedProject.projectDoc!.data!;
@@ -249,6 +257,53 @@ export class DraftGenerationStepsComponent extends SubscriptionDisposable implem
);
}
+ selectedTrainingBooksCollapsed(): TrainingGroup[] {
+ const continguousGroups: TrainingGroup[] = [];
+ let currentGroup: TrainingBook[] = [];
+ for (const book of this.userSelectedTrainingBooks) {
+ const isBookConsecutiveAndMatching =
+ book.source === currentGroup[0]?.source &&
+ book.target === currentGroup[0]?.target &&
+ book.number === currentGroup[currentGroup.length - 1]?.number + 1;
+ if (currentGroup.length > 0 && !isBookConsecutiveAndMatching) {
+ //process and reset current group
+ addGroup(currentGroup);
+ currentGroup.length = 0;
+ }
+ //add book to current group
+ currentGroup.push(book);
+ }
+
+ //add last group
+ if (currentGroup.length > 0) {
+ addGroup(currentGroup);
+ }
+
+ const groupsCollapsed: TrainingGroup[] = [];
+ for (const group of continguousGroups) {
+ const matchIndex = groupsCollapsed.findIndex(g => g.source === group.source && g.target === group.target);
+ if (matchIndex === -1) {
+ //make a new group for this source/target
+ groupsCollapsed.push(group);
+ } else {
+ //append the current group onto the matching group
+ groupsCollapsed[matchIndex].ranges.push(group.ranges[0]);
+ }
+ }
+
+ return groupsCollapsed;
+
+ function addGroup(group: TrainingBook[]): void {
+ let range;
+ if (group.length === 1) {
+ range = Canon.bookNumberToId(group[0].number);
+ } else {
+ range = Canon.bookNumberToId(group[0].number) + '-' + Canon.bookNumberToId(group[group.length - 1].number);
+ }
+ continguousGroups.push({ ranges: [range], source: group[0].source, target: group[0].target });
+ }
+ }
+
onTrainingBookSelect(selectedBooks: number[]): void {
this.userSelectedTrainingBooks = selectedBooks.map((bookNum: number) => ({
number: bookNum,