Add optional manual mode per translation and culture

This commit is contained in:
Thorsten Sommer 2022-09-21 22:52:17 +02:00
parent 10434c553a
commit 8a4bf6f180
Signed by: tsommer
GPG Key ID: 371BBA77A02C0108
8 changed files with 326 additions and 8 deletions

View File

@ -58,6 +58,7 @@ public sealed class DataContext : DbContext, IDataContext
modelBuilder.Entity<Translation>().HasIndex(n => n.Id); modelBuilder.Entity<Translation>().HasIndex(n => n.Id);
modelBuilder.Entity<Translation>().HasIndex(n => n.Culture); modelBuilder.Entity<Translation>().HasIndex(n => n.Culture);
modelBuilder.Entity<Translation>().HasIndex(n => n.Text); modelBuilder.Entity<Translation>().HasIndex(n => n.Text);
modelBuilder.Entity<Translation>().HasIndex(n => n.TranslateManual);
modelBuilder.Entity<Translation>().Navigation(n => n.TextElement).AutoInclude(); modelBuilder.Entity<Translation>().Navigation(n => n.TextElement).AutoInclude();
#endregion #endregion

View File

@ -9,4 +9,6 @@ public sealed class Translation
public string Culture { get; set; } = "en-US"; public string Culture { get; set; } = "en-US";
public string Text { get; set; } = string.Empty; public string Text { get; set; } = string.Empty;
public bool TranslateManual { get; set; } = false;
} }

View File

@ -0,0 +1,211 @@
// <auto-generated />
using System;
using DataModel.Database.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace DataModel.Migrations
{
[DbContext(typeof(DataContext))]
[Migration("20220921182526_202209AddManualFlag")]
partial class _202209AddManualFlag
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.9");
modelBuilder.Entity("DataModel.Database.Section", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("DataKey")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Depth")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("ParentId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("DataKey");
b.HasIndex("Depth");
b.HasIndex("Id");
b.HasIndex("Name");
b.HasIndex("ParentId");
b.ToTable("Sections");
});
modelBuilder.Entity("DataModel.Database.Setting", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<bool>("BoolValue")
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<Guid>("GuidValue")
.HasColumnType("TEXT");
b.Property<int>("IntegerValue")
.HasColumnType("INTEGER");
b.Property<string>("TextValue")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("BoolValue");
b.HasIndex("Code")
.IsUnique();
b.HasIndex("GuidValue");
b.HasIndex("Id");
b.HasIndex("IntegerValue");
b.HasIndex("TextValue");
b.ToTable("Settings");
});
modelBuilder.Entity("DataModel.Database.TextElement", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Code")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("IsMultiLine")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("SectionId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("Code");
b.HasIndex("Id");
b.HasIndex("IsMultiLine");
b.HasIndex("Name");
b.HasIndex("SectionId");
b.ToTable("TextElements");
});
modelBuilder.Entity("DataModel.Database.Translation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Culture")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Text")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("TextElementId")
.HasColumnType("INTEGER");
b.Property<bool>("TranslateManual")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("Culture");
b.HasIndex("Id");
b.HasIndex("Text");
b.HasIndex("TextElementId");
b.HasIndex("TranslateManual");
b.ToTable("Translations");
});
modelBuilder.Entity("DataModel.Database.Section", b =>
{
b.HasOne("DataModel.Database.Section", "Parent")
.WithMany()
.HasForeignKey("ParentId");
b.Navigation("Parent");
});
modelBuilder.Entity("DataModel.Database.TextElement", b =>
{
b.HasOne("DataModel.Database.Section", "Section")
.WithMany("TextElements")
.HasForeignKey("SectionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Section");
});
modelBuilder.Entity("DataModel.Database.Translation", b =>
{
b.HasOne("DataModel.Database.TextElement", "TextElement")
.WithMany("Translations")
.HasForeignKey("TextElementId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("TextElement");
});
modelBuilder.Entity("DataModel.Database.Section", b =>
{
b.Navigation("TextElements");
});
modelBuilder.Entity("DataModel.Database.TextElement", b =>
{
b.Navigation("Translations");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DataModel.Migrations
{
public partial class _202209AddManualFlag : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "TranslateManual",
table: "Translations",
type: "INTEGER",
nullable: false,
defaultValue: false);
migrationBuilder.CreateIndex(
name: "IX_Translations_TranslateManual",
table: "Translations",
column: "TranslateManual");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Translations_TranslateManual",
table: "Translations");
migrationBuilder.DropColumn(
name: "TranslateManual",
table: "Translations");
}
}
}

View File

@ -145,6 +145,9 @@ namespace DataModel.Migrations
b.Property<int>("TextElementId") b.Property<int>("TextElementId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<bool>("TranslateManual")
.HasColumnType("INTEGER");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("Culture"); b.HasIndex("Culture");
@ -155,6 +158,8 @@ namespace DataModel.Migrations
b.HasIndex("TextElementId"); b.HasIndex("TextElementId");
b.HasIndex("TranslateManual");
b.ToTable("Translations"); b.ToTable("Translations");
}); });

View File

@ -17,6 +17,7 @@ public static class TranslationProcessor
if(!await db.Translations.AnyAsync(n => n.TextElement == textElement && n.Culture == cultureInfo.Code)) if(!await db.Translations.AnyAsync(n => n.TextElement == textElement && n.Culture == cultureInfo.Code))
missedTranslations.Add(new Translation missedTranslations.Add(new Translation
{ {
TranslateManual = false,
Culture = cultureInfo.Code, Culture = cultureInfo.Code,
Text = string.Empty, Text = string.Empty,
}); });
@ -32,11 +33,12 @@ public static class TranslationProcessor
return await db.Translations.Where(n => n.TextElement == textElement).ToListAsync(); return await db.Translations.Where(n => n.TextElement == textElement).ToListAsync();
} }
public static async Task<ProcessorResult<Translation>> SaveChangedTranslation(int translationId, string text) public static async Task<ProcessorResult<Translation>> SaveChangedTranslation(int translationId, string text, bool manualFLag)
{ {
await using var db = ProcessorMeta.ServiceProvider.GetRequiredService<DataContext>(); await using var db = ProcessorMeta.ServiceProvider.GetRequiredService<DataContext>();
var dbTranslation = await db.Translations.FirstAsync(n => n.Id == translationId); var dbTranslation = await db.Translations.FirstAsync(n => n.Id == translationId);
dbTranslation.Text = text; dbTranslation.Text = text;
dbTranslation.TranslateManual = manualFLag;
try try
{ {

View File

@ -32,9 +32,12 @@
this.tableLayout = new System.Windows.Forms.TableLayoutPanel(); this.tableLayout = new System.Windows.Forms.TableLayoutPanel();
this.labelHead = new System.Windows.Forms.Label(); this.labelHead = new System.Windows.Forms.Label();
this.textBox = new System.Windows.Forms.TextBox(); this.textBox = new System.Windows.Forms.TextBox();
this.flowLayoutHeaderTools = new System.Windows.Forms.FlowLayoutPanel();
this.buttonDeepL = new System.Windows.Forms.Button(); this.buttonDeepL = new System.Windows.Forms.Button();
this.checkBoxManual = new System.Windows.Forms.CheckBox();
this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.tableLayout.SuspendLayout(); this.tableLayout.SuspendLayout();
this.flowLayoutHeaderTools.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
// tableLayout // tableLayout
@ -44,7 +47,7 @@
this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayout.Controls.Add(this.labelHead, 0, 0); this.tableLayout.Controls.Add(this.labelHead, 0, 0);
this.tableLayout.Controls.Add(this.textBox, 0, 1); this.tableLayout.Controls.Add(this.textBox, 0, 1);
this.tableLayout.Controls.Add(this.buttonDeepL, 1, 0); this.tableLayout.Controls.Add(this.flowLayoutHeaderTools, 1, 0);
this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayout.Location = new System.Drawing.Point(0, 0); this.tableLayout.Location = new System.Drawing.Point(0, 0);
this.tableLayout.Name = "tableLayout"; this.tableLayout.Name = "tableLayout";
@ -76,6 +79,18 @@
this.textBox.TabIndex = 1; this.textBox.TabIndex = 1;
this.textBox.TextChanged += new System.EventHandler(this.textBox_TextChanged); this.textBox.TextChanged += new System.EventHandler(this.textBox_TextChanged);
// //
// flowLayoutHeaderTools
//
this.flowLayoutHeaderTools.Controls.Add(this.buttonDeepL);
this.flowLayoutHeaderTools.Controls.Add(this.checkBoxManual);
this.flowLayoutHeaderTools.Dock = System.Windows.Forms.DockStyle.Fill;
this.flowLayoutHeaderTools.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
this.flowLayoutHeaderTools.Location = new System.Drawing.Point(366, 0);
this.flowLayoutHeaderTools.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutHeaderTools.Name = "flowLayoutHeaderTools";
this.flowLayoutHeaderTools.Size = new System.Drawing.Size(454, 66);
this.flowLayoutHeaderTools.TabIndex = 3;
//
// buttonDeepL // buttonDeepL
// //
this.buttonDeepL.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.buttonDeepL.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
@ -83,7 +98,7 @@
this.buttonDeepL.FlatAppearance.BorderSize = 0; this.buttonDeepL.FlatAppearance.BorderSize = 0;
this.buttonDeepL.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.buttonDeepL.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.buttonDeepL.Image = global::UI_WinForms.Resources.Icons.icons8_bot_512; this.buttonDeepL.Image = global::UI_WinForms.Resources.Icons.icons8_bot_512;
this.buttonDeepL.Location = new System.Drawing.Point(757, 3); this.buttonDeepL.Location = new System.Drawing.Point(391, 3);
this.buttonDeepL.Name = "buttonDeepL"; this.buttonDeepL.Name = "buttonDeepL";
this.buttonDeepL.Size = new System.Drawing.Size(60, 60); this.buttonDeepL.Size = new System.Drawing.Size(60, 60);
this.buttonDeepL.TabIndex = 2; this.buttonDeepL.TabIndex = 2;
@ -91,6 +106,19 @@
this.buttonDeepL.UseVisualStyleBackColor = true; this.buttonDeepL.UseVisualStyleBackColor = true;
this.buttonDeepL.Click += new System.EventHandler(this.buttonDeepL_Click); this.buttonDeepL.Click += new System.EventHandler(this.buttonDeepL_Click);
// //
// checkBoxManual
//
this.checkBoxManual.AutoSize = true;
this.checkBoxManual.Location = new System.Drawing.Point(188, 3);
this.checkBoxManual.Name = "checkBoxManual";
this.checkBoxManual.Padding = new System.Windows.Forms.Padding(0, 14, 0, 14);
this.checkBoxManual.Size = new System.Drawing.Size(197, 60);
this.checkBoxManual.TabIndex = 0;
this.checkBoxManual.Text = "Manual translation";
this.toolTip.SetToolTip(this.checkBoxManual, "Never overwrites this translation automatically");
this.checkBoxManual.UseVisualStyleBackColor = true;
this.checkBoxManual.CheckedChanged += new System.EventHandler(this.checkBoxManual_CheckedChanged);
//
// toolTip // toolTip
// //
this.toolTip.AutoPopDelay = 30000; this.toolTip.AutoPopDelay = 30000;
@ -109,6 +137,8 @@
this.Size = new System.Drawing.Size(820, 279); this.Size = new System.Drawing.Size(820, 279);
this.tableLayout.ResumeLayout(false); this.tableLayout.ResumeLayout(false);
this.tableLayout.PerformLayout(); this.tableLayout.PerformLayout();
this.flowLayoutHeaderTools.ResumeLayout(false);
this.flowLayoutHeaderTools.PerformLayout();
this.ResumeLayout(false); this.ResumeLayout(false);
} }
@ -120,5 +150,7 @@
private TextBox textBox; private TextBox textBox;
private Button buttonDeepL; private Button buttonDeepL;
private ToolTip toolTip; private ToolTip toolTip;
private FlowLayoutPanel flowLayoutHeaderTools;
private CheckBox checkBoxManual;
} }
} }

View File

@ -15,6 +15,7 @@ public sealed partial class Translation : UserControl
private bool isLoading = false; private bool isLoading = false;
private int currentTranslationId = -1; private int currentTranslationId = -1;
private bool isDeepLSourceCulture = false; private bool isDeepLSourceCulture = false;
private bool isManualOnlyMode = false;
private Translation? mainCultureTranslation = null; private Translation? mainCultureTranslation = null;
public Translation() public Translation()
@ -50,6 +51,7 @@ public sealed partial class Translation : UserControl
{ {
this.isDeepLSourceCulture = await AppSettings.GetDeepLSourceCultureIndex() == cultureInfo.Index; this.isDeepLSourceCulture = await AppSettings.GetDeepLSourceCultureIndex() == cultureInfo.Index;
this.textBox.ReadOnly = !(this.isDeepLSourceCulture || await AppSettings.GetDeepLAction() == SettingDeepLAction.MANUAL); this.textBox.ReadOnly = !(this.isDeepLSourceCulture || await AppSettings.GetDeepLAction() == SettingDeepLAction.MANUAL);
this.checkBoxManual.Visible = !this.isDeepLSourceCulture;
this.buttonDeepL.Visible = await AppSettings.GetDeepLMode() != SettingDeepLMode.DISABLED; this.buttonDeepL.Visible = await AppSettings.GetDeepLMode() != SettingDeepLMode.DISABLED;
this.buttonDeepL.Image = this.isDeepLSourceCulture ? Icons.icons8_trigger_1__svg : Icons.deepl_logo_icon_170284; this.buttonDeepL.Image = this.isDeepLSourceCulture ? Icons.icons8_trigger_1__svg : Icons.deepl_logo_icon_170284;
@ -66,9 +68,21 @@ public sealed partial class Translation : UserControl
{ {
this.isLoading = true; this.isLoading = true;
this.isManualOnlyMode = this.checkBoxManual.Checked = translation.TranslateManual;
this.currentTranslationId = translation.Id; this.currentTranslationId = translation.Id;
this.textBox.Text = translation.Text;
this.textBox.Multiline = translation.TextElement.IsMultiLine; try
{
this.textBox.Text = translation.Text;
this.textBox.Multiline = translation.TextElement.IsMultiLine;
this.textBox.ReadOnly = !(this.isDeepLSourceCulture || await AppSettings.GetDeepLAction() == SettingDeepLAction.MANUAL);
if (this.isManualOnlyMode)
this.textBox.ReadOnly = false;
}
catch (ObjectDisposedException)
{
}
this.Height = translation.TextElement.IsMultiLine ? 280 : 106; this.Height = translation.TextElement.IsMultiLine ? 280 : 106;
this.buttonDeepL.Visible = await AppSettings.GetDeepLMode() != SettingDeepLMode.DISABLED; this.buttonDeepL.Visible = await AppSettings.GetDeepLMode() != SettingDeepLMode.DISABLED;
@ -110,10 +124,12 @@ public sealed partial class Translation : UserControl
private async void SaveChanges(object? sender, ElapsedEventArgs e) private async void SaveChanges(object? sender, ElapsedEventArgs e)
{ {
if (this.currentTranslationId > -1) if (this.currentTranslationId > -1)
await TranslationProcessor.SaveChangedTranslation(this.currentTranslationId, this.textBox.Text); await TranslationProcessor.SaveChangedTranslation(this.currentTranslationId, this.textBox.Text, this.checkBoxManual.Checked);
if(this.ParentForm is UI_WinForms.Main main) if(this.ParentForm is UI_WinForms.Main main)
main.RemoveDeferredSaveOperation(this.currentTranslationId); main.RemoveDeferredSaveOperation(this.currentTranslationId);
this.isManualOnlyMode = this.checkBoxManual.Checked;
} }
private async void TriggerTranslateNow(object? sender, ElapsedEventArgs e) private async void TriggerTranslateNow(object? sender, ElapsedEventArgs e)
@ -129,11 +145,14 @@ public sealed partial class Translation : UserControl
internal string GetCurrentText() => this.textBox.Text; internal string GetCurrentText() => this.textBox.Text;
internal async Task Translate() internal async Task Translate(bool wasManualTriggered = false)
{ {
if (this.mainCultureTranslation is null) if (this.mainCultureTranslation is null)
return; return;
if(this.isManualOnlyMode && !wasManualTriggered)
return;
var text = await Processor.DeepL.Translate(this.mainCultureTranslation.GetCurrentText(), this.culture); var text = await Processor.DeepL.Translate(this.mainCultureTranslation.GetCurrentText(), this.culture);
if (this.textBox.InvokeRequired) if (this.textBox.InvokeRequired)
this.textBox.Invoke(() => this.textBox.Text = text); this.textBox.Invoke(() => this.textBox.Text = text);
@ -146,6 +165,17 @@ public sealed partial class Translation : UserControl
if (this.isDeepLSourceCulture) if (this.isDeepLSourceCulture)
this.TriggerTranslateNow(null, null); this.TriggerTranslateNow(null, null);
else else
await this.Translate(); await this.Translate(wasManualTriggered: true);
}
private async void checkBoxManual_CheckedChanged(object sender, EventArgs e)
{
if(this.isLoading)
return;
this.SaveChanges(null, null);
this.textBox.ReadOnly = !(this.isDeepLSourceCulture || await AppSettings.GetDeepLAction() == SettingDeepLAction.MANUAL);
if (this.isManualOnlyMode)
this.textBox.ReadOnly = false;
} }
} }