diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.html
new file mode 100644
index 0000000000..b99005bd84
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.html
@@ -0,0 +1,53 @@
+
Confirm project setup
+Training the language model
+
+
+
References
+
These are in the source language for the translation model.
+
+
+
+
Translation project
+
These are in the receptor language you are translating into.
+
+
+ @for (project of trainingSources; track project.paratextId) {
+
+ {{ project.name }}
+
+ Language code: {{ project.writingSystem.tag }}
+
+
+ }
+
+
arrow_right_alt
+
+ @for (project of trainingTargets; track project.paratextId) {
+
+ {{ project.name }}
+
+ Language code: {{ project.writingSystem.tag }}
+
+
+ }
+
+
+
+Drafting from
+This is the text that will be translated by the language model.
+
+ @for (project of draftingSources; track project.paratextId) {
+
+ {{ project.name }}
+
+ Language code: {{ project.writingSystem.tag }}
+
+
+ }
+
+
+
+ Incorrect language codes will dramatically reduce draft quality.
+ Language codes can be changed in Paratext by going to Project Settings > Project Properties > Language.
+ All the language codes are correct.
+
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.scss b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.scss
new file mode 100644
index 0000000000..18312c052b
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.scss
@@ -0,0 +1,79 @@
+.training-data {
+ display: grid;
+ grid-template-areas: '. . .' '. . .';
+ row-gap: 1em;
+}
+
+.gap,
+.arrow {
+ padding-inline: 2em;
+}
+
+.sources,
+.targets,
+.arrow {
+ background: #f0f0f0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ padding-block: 1em;
+ gap: 1em;
+}
+
+.source-description,
+.sources,
+.translation-data-description,
+.translation-data {
+ padding-inline-start: 1em;
+}
+
+.target-description,
+.targets {
+ padding-inline-end: 1em;
+}
+
+.source-description p,
+.target-description p,
+.translation-data-description {
+ font-style: italic;
+ font-size: 0.95em;
+}
+
+.training-data h3 {
+ margin-block: 0 0.5em;
+}
+
+.training-data p {
+ margin: 0;
+}
+
+h1,
+h2,
+h3,
+h4,
+strong {
+ font-weight: 500;
+}
+
+h1 {
+ margin-bottom: 0;
+}
+
+h2 {
+ margin-top: 2em;
+}
+
+.project {
+ display: flex;
+ flex-direction: column;
+ row-gap: 0.25em;
+}
+
+.project-name {
+ font-size: 1.1em;
+ font-weight: 500;
+}
+
+.translation-data {
+ margin-bottom: 2.5em;
+}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.ts
new file mode 100644
index 0000000000..70b2fe6e9f
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.component.ts
@@ -0,0 +1,58 @@
+import { Component, EventEmitter, Output } from '@angular/core';
+import { MatCheckboxChange, MatCheckboxModule } from '@angular/material/checkbox';
+import { MatIconModule } from '@angular/material/icon';
+import { TranslocoModule } from '@ngneat/transloco';
+import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
+import { TranslateSource } from 'realtime-server/lib/esm/scriptureforge/models/translate-config';
+import { ActivatedProjectService } from '../../../../xforge-common/activated-project.service';
+import { NoticeComponent } from '../../../shared/notice/notice.component';
+
+@Component({
+ selector: 'app-confirm-sources',
+ standalone: true,
+ imports: [TranslocoModule, NoticeComponent, MatCheckboxModule, MatIconModule],
+ templateUrl: './confirm-sources.component.html',
+ styleUrl: './confirm-sources.component.scss'
+})
+export class ConfirmSourcesComponent {
+ @Output() languageCodesVerified = new EventEmitter(false);
+
+ trainingSources: TranslateSource[] = [];
+ trainingTargets: SFProjectProfile[] = [];
+ draftingSources: TranslateSource[] = [];
+
+ constructor(activatedProjectService: ActivatedProjectService) {
+ const project = activatedProjectService.projectDoc!.data!;
+ this.trainingTargets.push(project);
+
+ let trainingSource: TranslateSource | undefined;
+ if (project.translateConfig.draftConfig.alternateTrainingSourceEnabled) {
+ trainingSource = project.translateConfig.draftConfig.alternateTrainingSource;
+ } else {
+ trainingSource = project.translateConfig.source;
+ }
+
+ if (trainingSource != null) {
+ this.trainingSources.push(trainingSource);
+ }
+
+ if (project.translateConfig.draftConfig.additionalTrainingSourceEnabled) {
+ this.trainingSources.push(project.translateConfig.draftConfig.additionalTrainingSource!);
+ }
+
+ let draftingSource: TranslateSource | undefined;
+ if (project.translateConfig.draftConfig.alternateSourceEnabled) {
+ draftingSource = project.translateConfig.draftConfig.alternateSource;
+ } else {
+ draftingSource = project.translateConfig.source;
+ }
+
+ if (draftingSource != null) {
+ this.draftingSources.push(draftingSource);
+ }
+ }
+
+ confirmationChanged(change: MatCheckboxChange): void {
+ this.languageCodesVerified.emit(change.checked);
+ }
+}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.stories.ts
new file mode 100644
index 0000000000..f32c71b68c
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/confirm-sources/confirm-sources.stories.ts
@@ -0,0 +1,78 @@
+import { CommonModule } from '@angular/common';
+import { TranslocoModule } from '@ngneat/transloco';
+import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
+// import { I18nStoryModule } from '../../../../xforge-common/i18n-story.module';
+// import { UICommonModule } from '../../../../xforge-common/ui-common.module';
+import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
+import { instance, mock, when } from 'ts-mockito';
+import { ActivatedProjectService } from '../../../../xforge-common/activated-project.service';
+import { SFProjectProfileDoc } from '../../../core/models/sf-project-profile-doc';
+import { ConfirmSourcesComponent } from './confirm-sources.component';
+
+const mockedActivatedProjectService = mock(ActivatedProjectService);
+
+when(mockedActivatedProjectService.projectDoc).thenReturn({
+ data: createTestProjectProfile({
+ name: 'Test Project',
+ translateConfig: {
+ source: {
+ projectRef: 'source-project',
+ shortName: 'SP',
+ name: 'THIS PROJECT SHOULD NOT BE SHOWN!!!!!****',
+ paratextId: 'source-project',
+ writingSystem: { tag: 'es' }
+ },
+ draftConfig: {
+ alternateTrainingSourceEnabled: true,
+ alternateTrainingSource: {
+ projectRef: 'alternate-training-source',
+ shortName: 'ATS',
+ name: 'Alternate Training Source',
+ paratextId: 'alternate-training-source',
+ writingSystem: { tag: 'es' }
+ },
+ additionalTrainingSourceEnabled: true,
+ additionalTrainingSource: {
+ projectRef: 'additional-training-source',
+ shortName: 'ATS',
+ name: 'Additional Training Source',
+ paratextId: 'additional-training-source',
+ writingSystem: { tag: 'es' }
+ },
+ alternateSourceEnabled: true,
+ alternateSource: {
+ projectRef: 'alternate-drafting-source',
+ shortName: 'ADS',
+ name: 'Alternate Drafting Source',
+ paratextId: 'alternate-drafting-source',
+ writingSystem: { tag: 'es' }
+ }
+ }
+ }
+ })
+} as SFProjectProfileDoc);
+
+const meta: Meta = {
+ title: 'Translate/ConfirmSources',
+ component: ConfirmSourcesComponent,
+ decorators: [
+ moduleMetadata({
+ imports: [CommonModule, TranslocoModule],
+ providers: [{ provide: ActivatedProjectService, useValue: instance(mockedActivatedProjectService) }]
+ })
+ ]
+};
+
+export default meta;
+
+interface StoryState {}
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ book: 1,
+ progress: 0.37,
+ hues: [0]
+ }
+};
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 f454b62eb4..1f74878bec 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
@@ -1,6 +1,20 @@
@if (availableTranslateBooks && availableTranslateBooks.length > 0) {
-
+
+
+ Confirm setup
+
+ @if (nextClickedOnLanguageVerification && !languagesVerified) {
+
+ Please confirm the language codes are correct before continuing.
+
+ }
+
+
+
+
0">
{{ t("choose_books_to_translate") }}
@@ -36,9 +50,8 @@
}
-
+
+
0">
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 e9025d4506..111321234b 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
@@ -1,3 +1,8 @@
+:host {
+ display: block;
+ max-width: 80em;
+}
+
.stepper-multi-header {
h2,
h3 {
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 8b4e85b4ae..17e73f532c 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
@@ -17,6 +17,7 @@ import { BookMultiSelectComponent } from '../../../shared/book-multi-select/book
import { ProgressService } from '../../../shared/progress-service/progress.service';
import { SharedModule } from '../../../shared/shared.module';
import { NllbLanguageService } from '../../nllb-language.service';
+import { ConfirmSourcesComponent } from '../confirm-sources/confirm-sources.component';
import { DraftSource, DraftSourcesService } from '../draft-sources.service';
import { TrainingDataMultiSelectComponent } from '../training-data/training-data-multi-select.component';
import { TrainingDataUploadDialogComponent } from '../training-data/training-data-upload-dialog.component';
@@ -43,13 +44,17 @@ export interface DraftGenerationStepsResult {
TranslocoMarkupModule,
BookMultiSelectComponent,
TrainingDataMultiSelectComponent,
- TrainingDataUploadDialogComponent
+ TrainingDataUploadDialogComponent,
+ ConfirmSourcesComponent
]
})
export class DraftGenerationStepsComponent extends SubscriptionDisposable implements OnInit {
@Output() done = new EventEmitter();
@ViewChild(MatStepper) stepper!: MatStepper;
+ languagesVerified = false;
+ nextClickedOnLanguageVerification = false;
+
availableTranslateBooks?: number[] = undefined;
availableTrainingBooks: number[] = [];
availableTrainingData: Readonly[] = [];
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation.component.ts
index d32f89f505..aa12db458f 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation.component.ts
@@ -32,6 +32,7 @@ import { ServalProjectComponent } from '../../serval-administration/serval-proje
import { SharedModule } from '../../shared/shared.module';
import { WorkingAnimatedIndicatorComponent } from '../../shared/working-animated-indicator/working-animated-indicator.component';
import { NllbLanguageService } from '../nllb-language.service';
+import { ConfirmSourcesComponent } from './confirm-sources/confirm-sources.component';
import { BuildConfig, DraftZipProgress, activeBuildStates } from './draft-generation';
import {
DraftGenerationStepsComponent,
@@ -61,7 +62,8 @@ import { SupportedBackTranslationLanguagesDialogComponent } from './supported-ba
DraftInformationComponent,
SupportedBackTranslationLanguagesDialogComponent,
ServalProjectComponent,
- DraftPreviewBooksComponent
+ DraftPreviewBooksComponent,
+ ConfirmSourcesComponent
]
})
export class DraftGenerationComponent extends DataLoadingComponent implements OnInit {