From aeae8886003fb9dd32a1705272f034e696c1b551 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sat, 21 Oct 2023 17:38:59 -0500 Subject: [PATCH 001/113] refactored the PyScriptAutoConfigDialog in preparation for copying it for Python 3 implementation --- .../PyScriptAutoConfigDialog.Designer.cs | 231 ++++++++ src/PyScriptEC/PyScriptAutoConfigDialog.cs | 546 +++++------------- src/PyScriptEC/PyScriptEC 2010.csproj | 6 + src/PyScriptEC/PyScriptEncConverter.cs | 6 +- src/PyScriptEC/PythonAutoConfigDialog.cs | 12 + 5 files changed, 406 insertions(+), 395 deletions(-) create mode 100644 src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs create mode 100644 src/PyScriptEC/PythonAutoConfigDialog.cs diff --git a/src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs b/src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs new file mode 100644 index 00000000..563d85df --- /dev/null +++ b/src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SilEncConverters40 +{ + partial class PyScriptAutoConfigDialog + { + #region Windows Form Designer generated code + // This code does not get generated by Designer, so modify it directly. + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelScriptFile = new System.Windows.Forms.Label(); + this.textBoxFileSpec = new System.Windows.Forms.TextBox(); + this.buttonBrowse = new System.Windows.Forms.Button(); + this.groupBoxExpects = new System.Windows.Forms.GroupBox(); + this.radioButtonExpectsUnicode = new System.Windows.Forms.RadioButton(); + this.radioButtonExpectsLegacy = new System.Windows.Forms.RadioButton(); + this.groupBoxReturns = new System.Windows.Forms.GroupBox(); + this.radioButtonReturnsUnicode = new System.Windows.Forms.RadioButton(); + this.radioButtonReturnsLegacy = new System.Windows.Forms.RadioButton(); + this.openFileDialogBrowse = new System.Windows.Forms.OpenFileDialog(); + this.tabControl.SuspendLayout(); + this.tabPageSetup.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.groupBoxExpects.SuspendLayout(); + this.groupBoxReturns.SuspendLayout(); + this.SuspendLayout(); + // + // tabPageSetup + // + this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); + // + // buttonApply + // + this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonApply, true); + // + // buttonCancel + // + this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); + this.helpProvider.SetShowHelp(this.buttonCancel, true); + // + // buttonOK + // + this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonOK, true); + // + // buttonSaveInRepository + // + this.helpProvider.SetHelpString(this.buttonSaveInRepository, "Click to add this converter to the system repository permanently."); + this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 104F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.labelScriptFile, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxFileSpec, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.buttonBrowse, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.groupBoxExpects, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.groupBoxReturns, 1, 3); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); + this.tableLayoutPanel1.TabIndex = 1; + // + // labelScriptFile + // + this.labelScriptFile.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelScriptFile.AutoSize = true; + this.labelScriptFile.Location = new System.Drawing.Point(14, 18); + this.labelScriptFile.Name = "labelScriptFile"; + this.labelScriptFile.Size = new System.Drawing.Size(87, 13); + this.labelScriptFile.TabIndex = 0; + this.labelScriptFile.Text = "Python script file:"; + // + // textBoxFileSpec + // + this.textBoxFileSpec.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.textBoxFileSpec.Location = new System.Drawing.Point(104, 15); + this.textBoxFileSpec.Margin = new System.Windows.Forms.Padding(0); + this.textBoxFileSpec.Name = "textBoxFileSpec"; + this.textBoxFileSpec.Size = new System.Drawing.Size(390, 20); + this.textBoxFileSpec.TabIndex = 1; + this.textBoxFileSpec.TextChanged += new System.EventHandler(this.textBoxFileSpec_TextChanged); + // + // buttonBrowse + // + this.buttonBrowse.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.buttonBrowse.AutoSize = true; + this.buttonBrowse.Location = new System.Drawing.Point(494, 13); + this.buttonBrowse.Margin = new System.Windows.Forms.Padding(0); + this.buttonBrowse.Name = "buttonBrowse"; + this.buttonBrowse.Size = new System.Drawing.Size(75, 23); + this.buttonBrowse.TabIndex = 2; + this.buttonBrowse.Text = "Browse..."; + this.buttonBrowse.Click += new System.EventHandler(this.buttonBrowse_Click); + // + // groupBoxExpects + // + this.groupBoxExpects.Controls.Add(this.radioButtonExpectsUnicode); + this.groupBoxExpects.Controls.Add(this.radioButtonExpectsLegacy); + this.groupBoxExpects.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxExpects.Location = new System.Drawing.Point(107, 136); + this.groupBoxExpects.Name = "groupBoxExpects"; + this.groupBoxExpects.Size = new System.Drawing.Size(384, 77); + this.groupBoxExpects.TabIndex = 3; + this.groupBoxExpects.TabStop = false; + this.groupBoxExpects.Text = "Python function expects"; + this.groupBoxExpects.Visible = false; + // + // radioButtonExpectsUnicode + // + this.radioButtonExpectsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonExpectsUnicode.AutoSize = true; + this.radioButtonExpectsUnicode.Location = new System.Drawing.Point(50, 30); + this.radioButtonExpectsUnicode.Name = "radioButtonExpectsUnicode"; + this.radioButtonExpectsUnicode.Size = new System.Drawing.Size(95, 17); + this.radioButtonExpectsUnicode.TabIndex = 0; + this.radioButtonExpectsUnicode.TabStop = true; + this.radioButtonExpectsUnicode.Text = "Unicode String"; + this.radioButtonExpectsUnicode.UseVisualStyleBackColor = true; + this.radioButtonExpectsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // radioButtonExpectsLegacy + // + this.radioButtonExpectsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonExpectsLegacy.AutoSize = true; + this.radioButtonExpectsLegacy.Location = new System.Drawing.Point(200, 30); + this.radioButtonExpectsLegacy.Name = "radioButtonExpectsLegacy"; + this.radioButtonExpectsLegacy.Size = new System.Drawing.Size(117, 17); + this.radioButtonExpectsLegacy.TabIndex = 0; + this.radioButtonExpectsLegacy.TabStop = true; + this.radioButtonExpectsLegacy.Text = "Non-Unicode Bytes"; + this.radioButtonExpectsLegacy.UseVisualStyleBackColor = true; + this.radioButtonExpectsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // groupBoxReturns + // + this.groupBoxReturns.Controls.Add(this.radioButtonReturnsUnicode); + this.groupBoxReturns.Controls.Add(this.radioButtonReturnsLegacy); + this.groupBoxReturns.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxReturns.Location = new System.Drawing.Point(107, 219); + this.groupBoxReturns.Name = "groupBoxReturns"; + this.groupBoxReturns.Size = new System.Drawing.Size(384, 77); + this.groupBoxReturns.TabIndex = 4; + this.groupBoxReturns.TabStop = false; + this.groupBoxReturns.Text = "Python function returns"; + this.groupBoxReturns.Visible = false; + // + // radioButtonReturnsUnicode + // + this.radioButtonReturnsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonReturnsUnicode.AutoSize = true; + this.radioButtonReturnsUnicode.Location = new System.Drawing.Point(50, 30); + this.radioButtonReturnsUnicode.Name = "radioButtonReturnsUnicode"; + this.radioButtonReturnsUnicode.Size = new System.Drawing.Size(95, 17); + this.radioButtonReturnsUnicode.TabIndex = 0; + this.radioButtonReturnsUnicode.TabStop = true; + this.radioButtonReturnsUnicode.Text = "Unicode String"; + this.radioButtonReturnsUnicode.UseVisualStyleBackColor = true; + this.radioButtonReturnsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // radioButtonReturnsLegacy + // + this.radioButtonReturnsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonReturnsLegacy.AutoSize = true; + this.radioButtonReturnsLegacy.Location = new System.Drawing.Point(200, 30); + this.radioButtonReturnsLegacy.Name = "radioButtonReturnsLegacy"; + this.radioButtonReturnsLegacy.Size = new System.Drawing.Size(118, 17); + this.radioButtonReturnsLegacy.TabIndex = 0; + this.radioButtonReturnsLegacy.TabStop = true; + this.radioButtonReturnsLegacy.Text = "Non-Unicode String"; + this.radioButtonReturnsLegacy.UseVisualStyleBackColor = true; + this.radioButtonReturnsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // openFileDialogBrowse + // + this.openFileDialogBrowse.DefaultExt = "py"; + this.openFileDialogBrowse.Filter = "Python scrips (*.py)|*.py"; + this.openFileDialogBrowse.Title = "Browse for Python script"; + // + // PyScriptAutoConfigDialog + // + this.ClientSize = new System.Drawing.Size(634, 479); + this.Name = "PyScriptAutoConfigDialog"; + this.Controls.SetChildIndex(this.tabControl, 0); + this.Controls.SetChildIndex(this.buttonApply, 0); + this.Controls.SetChildIndex(this.buttonCancel, 0); + this.Controls.SetChildIndex(this.buttonOK, 0); + this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); + this.tabControl.ResumeLayout(false); + this.tabPageSetup.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.groupBoxExpects.ResumeLayout(false); + this.groupBoxExpects.PerformLayout(); + this.groupBoxReturns.ResumeLayout(false); + this.groupBoxReturns.PerformLayout(); + this.ResumeLayout(false); + } + + #endregion + + private System.Windows.Forms.Label labelScriptFile; + private System.Windows.Forms.TextBox textBoxFileSpec; + private System.Windows.Forms.Button buttonBrowse; + private System.Windows.Forms.OpenFileDialog openFileDialogBrowse; + private System.Windows.Forms.GroupBox groupBoxExpects; + private System.Windows.Forms.RadioButton radioButtonExpectsUnicode; + private System.Windows.Forms.RadioButton radioButtonExpectsLegacy; + private System.Windows.Forms.GroupBox groupBoxReturns; + private System.Windows.Forms.RadioButton radioButtonReturnsLegacy; + private System.Windows.Forms.RadioButton radioButtonReturnsUnicode; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + } +} diff --git a/src/PyScriptEC/PyScriptAutoConfigDialog.cs b/src/PyScriptEC/PyScriptAutoConfigDialog.cs index 0bf64a81..48e9badb 100755 --- a/src/PyScriptEC/PyScriptAutoConfigDialog.cs +++ b/src/PyScriptEC/PyScriptAutoConfigDialog.cs @@ -12,412 +12,174 @@ namespace SilEncConverters40 { - public class PyScriptAutoConfigDialog : SilEncConverters40.AutoConfigDialog - { - public PyScriptAutoConfigDialog ( - IEncConverters aECs, - string strDisplayName, - string strFriendlyName, - string strConverterIdentifier, - ConvType eConversionType, - string strLhsEncodingId, - string strRhsEncodingId, - int lProcessTypeFlags, - bool bIsInRepository) - { - Util.DebugWriteLine(this, "ctor1 BEGIN"); + public partial class PyScriptAutoConfigDialog : PythonAutoConfigDialog + { + public PyScriptAutoConfigDialog( + IEncConverters aECs, + string strDisplayName, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strLhsEncodingId, + string strRhsEncodingId, + int lProcessTypeFlags, + bool bIsInRepository) + { + Util.DebugWriteLine(this, "ctor1 BEGIN"); InitializeComponent(); - Util.DebugWriteLine(this, "Initialized component."); - base.Initialize ( - aECs, - PyScriptEncConverter.strHtmlFilename, - strDisplayName, - strFriendlyName, - strConverterIdentifier, - eConversionType, - strLhsEncodingId, - strRhsEncodingId, - lProcessTypeFlags | (int)ProcessTypeFlags.PythonScript, - bIsInRepository); - Util.DebugWriteLine(this, "Initialized base."); - // if we're editing a CC table/spellfixer project, then set the - // Converter Spec and say it's unmodified - if (m_bEditMode) - { - Util.DebugWriteLine(this, "Edit mode"); + Util.DebugWriteLine(this, "Initialized component."); + base.Initialize( + aECs, + PyScriptEncConverter.strHtmlFilename, + strDisplayName, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strLhsEncodingId, + strRhsEncodingId, + lProcessTypeFlags | (int)ProcessTypeFlags.PythonScript, + bIsInRepository); + Util.DebugWriteLine(this, "Initialized base."); + // if we're editing a CC table/spellfixer project, then set the + // Converter Spec and say it's unmodified + if (m_bEditMode) + { + Util.DebugWriteLine(this, "Edit mode"); System.Diagnostics.Debug.Assert( - !String.IsNullOrEmpty(ConverterIdentifier)); + !String.IsNullOrEmpty(ConverterIdentifier)); textBoxFileSpec.Text = ConverterIdentifier; - IsModified = false; - } - m_bInitialized = true; - Util.DebugWriteLine(this, "END"); + IsModified = false; + } + m_bInitialized = true; + Util.DebugWriteLine(this, "END"); } - public PyScriptAutoConfigDialog ( - IEncConverters aECs, - string strFriendlyName, - string strConverterIdentifier, - ConvType eConversionType, - string strTestData) - { - Util.DebugWriteLine(this, "ctor2 BEGIN"); - InitializeComponent(); - base.Initialize ( - aECs, - strFriendlyName, - strConverterIdentifier, - eConversionType, - strTestData); - Util.DebugWriteLine(this, "END"); - } - - private System.Windows.Forms.Label labelScriptFile; - private System.Windows.Forms.TextBox textBoxFileSpec; - private System.Windows.Forms.Button buttonBrowse; - private System.Windows.Forms.OpenFileDialog openFileDialogBrowse; - - private System.Windows.Forms.GroupBox groupBoxExpects; - private System.Windows.Forms.RadioButton radioButtonExpectsUnicode; - private System.Windows.Forms.RadioButton radioButtonExpectsLegacy; - private System.Windows.Forms.GroupBox groupBoxReturns; - private System.Windows.Forms.RadioButton radioButtonReturnsLegacy; - private System.Windows.Forms.RadioButton radioButtonReturnsUnicode; - - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - - // This code does not get generated by Designer, so modify it directly. - private void InitializeComponent() - { - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.labelScriptFile = new System.Windows.Forms.Label(); - this.textBoxFileSpec = new System.Windows.Forms.TextBox(); - this.buttonBrowse = new System.Windows.Forms.Button(); - this.openFileDialogBrowse = new System.Windows.Forms.OpenFileDialog(); - - this.groupBoxExpects = new System.Windows.Forms.GroupBox(); - this.radioButtonExpectsLegacy = new System.Windows.Forms.RadioButton(); - this.radioButtonExpectsUnicode = new System.Windows.Forms.RadioButton(); - this.groupBoxReturns = new System.Windows.Forms.GroupBox(); - this.radioButtonReturnsLegacy = new System.Windows.Forms.RadioButton(); - this.radioButtonReturnsUnicode = new System.Windows.Forms.RadioButton(); - - this.tabControl.SuspendLayout(); - this.tabPageSetup.SuspendLayout(); - this.tableLayoutPanel1.SuspendLayout(); - this.groupBoxExpects.SuspendLayout(); - this.groupBoxReturns.SuspendLayout(); - this.SuspendLayout(); - - // - // tableLayoutPanel1 - // - this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.ColumnCount = 3; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.RowCount = 4; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 30F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 70F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); - this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.TabIndex = 1; - - this.tableLayoutPanel1.Controls.Add(this.labelScriptFile, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.textBoxFileSpec, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.buttonBrowse, 2, 0); - this.tableLayoutPanel1.Controls.Add(this.groupBoxExpects, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.groupBoxReturns, 1, 2); - - // - // labelScriptFile - // - this.labelScriptFile.Name = "labelScriptFile"; - this.labelScriptFile.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.labelScriptFile.AutoSize = true; - this.labelScriptFile.Text = "Python script file:"; - this.labelScriptFile.TabIndex = 0; - // - // textBoxFileSpec - // - this.textBoxFileSpec.Name = "textBoxFileSpec"; - this.textBoxFileSpec.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.textBoxFileSpec.Size = new System.Drawing.Size(390, 30); - this.textBoxFileSpec.Margin = new Padding(0); - this.textBoxFileSpec.TabIndex = 1; - this.textBoxFileSpec.TextChanged += new System.EventHandler(this.textBoxFileSpec_TextChanged); - // - // buttonBrowse - // - this.buttonBrowse.Name = "buttonBrowse"; - this.buttonBrowse.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.buttonBrowse.AutoSize = true; - this.buttonBrowse.Margin = new Padding(0); - this.buttonBrowse.Text = "Browse..."; - this.buttonBrowse.TabIndex = 2; - this.buttonBrowse.Click += new System.EventHandler(this.buttonBrowse_Click); - // - // openFileDialogBrowse - // - this.openFileDialogBrowse.DefaultExt = "py"; - this.openFileDialogBrowse.Filter = "Python scrips (*.py)|*.py"; - this.openFileDialogBrowse.Title = "Browse for Python script"; - - // - // groupBoxExpects - // - this.groupBoxExpects.Controls.Add(this.radioButtonExpectsUnicode); - this.groupBoxExpects.Controls.Add(this.radioButtonExpectsLegacy); - this.groupBoxExpects.Dock = System.Windows.Forms.DockStyle.Fill; - this.groupBoxExpects.Name = "groupBoxExpects"; - this.groupBoxExpects.Size = new System.Drawing.Size(384, 77); - this.groupBoxExpects.TabIndex = 3; - this.groupBoxExpects.TabStop = false; - this.groupBoxExpects.Text = "Python function expects"; - // - // radioButtonExpectsUnicode - // - this.radioButtonExpectsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonExpectsUnicode.AutoSize = true; - this.radioButtonExpectsUnicode.Location = new System.Drawing.Point(50, 30); - this.radioButtonExpectsUnicode.Name = "radioButtonExpectsUnicode"; - this.radioButtonExpectsUnicode.Size = new System.Drawing.Size(100, 17); - this.radioButtonExpectsUnicode.TabIndex = 0; - this.radioButtonExpectsUnicode.TabStop = true; - this.radioButtonExpectsUnicode.Text = "Unicode String"; - this.radioButtonExpectsUnicode.UseVisualStyleBackColor = true; - this.radioButtonExpectsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - // - // radioButtonExpectsLegacy - // - this.radioButtonExpectsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonExpectsLegacy.AutoSize = true; - this.radioButtonExpectsLegacy.Location = new System.Drawing.Point(200, 30); - this.radioButtonExpectsLegacy.Name = "radioButtonExpectsLegacy"; - this.radioButtonExpectsLegacy.Size = new System.Drawing.Size(125, 17); - this.radioButtonExpectsLegacy.TabIndex = 0; - this.radioButtonExpectsLegacy.TabStop = true; - this.radioButtonExpectsLegacy.Text = "Non-Unicode Bytes"; - this.radioButtonExpectsLegacy.UseVisualStyleBackColor = true; - this.radioButtonExpectsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - // - // groupBoxReturns - // - this.groupBoxReturns.Controls.Add(this.radioButtonReturnsUnicode); - this.groupBoxReturns.Controls.Add(this.radioButtonReturnsLegacy); - this.groupBoxReturns.Dock = System.Windows.Forms.DockStyle.Fill; - this.groupBoxReturns.Name = "groupBoxReturns"; - this.groupBoxReturns.Size = new System.Drawing.Size(384, 77); - this.groupBoxReturns.TabIndex = 4; - this.groupBoxReturns.TabStop = false; - this.groupBoxReturns.Text = "Python function returns"; - // - // radioButtonReturnsUnicode - // - this.radioButtonReturnsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonReturnsUnicode.AutoSize = true; - this.radioButtonReturnsUnicode.Location = new System.Drawing.Point(50, 30); - this.radioButtonReturnsUnicode.Name = "radioButtonReturnsUnicode"; - this.radioButtonReturnsUnicode.Size = new System.Drawing.Size(100, 17); - this.radioButtonReturnsUnicode.TabIndex = 0; - this.radioButtonReturnsUnicode.TabStop = true; - this.radioButtonReturnsUnicode.Text = "Unicode String"; - this.radioButtonReturnsUnicode.UseVisualStyleBackColor = true; - this.radioButtonReturnsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - // - // radioButtonReturnsLegacy - // - this.radioButtonReturnsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonReturnsLegacy.AutoSize = true; - this.radioButtonReturnsLegacy.Location = new System.Drawing.Point(200, 30); - this.radioButtonReturnsLegacy.Name = "radioButtonReturnsLegacy"; - this.radioButtonReturnsLegacy.Size = new System.Drawing.Size(125, 17); - this.radioButtonReturnsLegacy.TabIndex = 0; - this.radioButtonReturnsLegacy.TabStop = true; - this.radioButtonReturnsLegacy.Text = "Non-Unicode String"; - this.radioButtonReturnsLegacy.UseVisualStyleBackColor = true; - this.radioButtonReturnsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - - // - // Button Help - // - this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); - this.helpProvider.SetShowHelp( this.buttonApply, true); - this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); - this.helpProvider.SetShowHelp( this.buttonCancel, true); - this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); - this.helpProvider.SetShowHelp( this.buttonOK, true); - this.helpProvider.SetHelpString(this.buttonSaveInRepository, "Click to add this converter to the system repository permanently."); - this.helpProvider.SetShowHelp( this.buttonSaveInRepository, true); - - // - // PyScriptAutoConfigDialog - // - this.ClientSize = new System.Drawing.Size(634, 479); - this.Name = "PyScriptAutoConfigDialog"; - this.Controls.SetChildIndex(this.tabControl, 0); - this.Controls.SetChildIndex(this.buttonApply, 0); - this.Controls.SetChildIndex(this.buttonCancel, 0); - this.Controls.SetChildIndex(this.buttonOK, 0); - this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); - this.tabControl.ResumeLayout(false); - this.tabPageSetup.ResumeLayout(false); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - this.groupBoxExpects.ResumeLayout(false); - this.groupBoxExpects.PerformLayout(); - this.groupBoxReturns.ResumeLayout(false); - this.groupBoxReturns.PerformLayout(); - this.ResumeLayout(false); - } - - protected void UpdateUI(bool bVisible) - { - Util.DebugWriteLine(this, "BEGIN"); - buttonSaveInRepository.Visible = - groupBoxExpects.Visible = - groupBoxReturns.Visible = bVisible; - Util.DebugWriteLine(this, "END"); + public PyScriptAutoConfigDialog( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData) + { + Util.DebugWriteLine(this, "ctor2 BEGIN"); + InitializeComponent(); + base.Initialize( + aECs, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strTestData); + Util.DebugWriteLine(this, "END"); } - protected override void SetConvTypeControls() - { - SetRbValuesFromConvType(radioButtonExpectsUnicode, radioButtonExpectsLegacy, radioButtonReturnsUnicode, - radioButtonReturnsLegacy); - } - - // this method is called either when the user clicks the "Apply" or "OK" buttons *OR* if she - // tries to switch to the Test or Advanced tab. This is the dialog's one opportunity - // to make sure that the user has correctly configured a legitimate converter. - protected override bool OnApply() - { - Util.DebugWriteLine(this, "BEGIN"); - // Get the converter identifier from the Setup tab controls. - ConverterIdentifier = textBoxFileSpec.Text; - SetConvTypeFromRbControls(radioButtonExpectsUnicode, radioButtonExpectsLegacy, - radioButtonReturnsUnicode, radioButtonReturnsLegacy); - - // if we're actually on the setup tab, then do some further checking as well. - if (tabControl.SelectedTab == tabPageSetup) - { - // only do these message boxes if we're on the Setup tab itself, because if this OnApply - // is being called as a result of the user switching to the Test tab, that code will - // already put up an error message and we don't need two error messages. - if (String.IsNullOrEmpty(ConverterIdentifier)) - { - MessageBox.Show(this, "Choose a Python script first!", EncConverters.cstrCaption); - return false; - } - else if (!File.Exists(ConverterIdentifier)) - { - MessageBox.Show(this, "File doesn't exist!", EncConverters.cstrCaption); - return false; - } - } - Util.DebugWriteLine(this, "END"); - return base.OnApply(); - } - -/* - protected override bool ShouldRemoveBeforeAdd - { - get { return true; } - } - - protected override bool ShouldFriendlyNameBeReadOnly - { - get { return false; } - } - - protected override bool GetFontMapping(string strFriendlyName, out string strLhsFont, out string strRhsFont) - { - return base.GetFontMapping(strFriendlyName, out strLhsFont, out strRhsFont); - } -*/ - - protected override string ProgID - { - get { return typeof(PyScriptEncConverter).FullName; } - } + protected void UpdateUI(bool bVisible) + { + Util.DebugWriteLine(this, "BEGIN"); + buttonSaveInRepository.Visible = + groupBoxExpects.Visible = + groupBoxReturns.Visible = bVisible; + Util.DebugWriteLine(this, "END"); + } - protected override string ImplType - { - get { return EncConverters.strTypeSILPyScript; } - } + protected override void SetConvTypeControls() + { + SetRbValuesFromConvType(radioButtonExpectsUnicode, radioButtonExpectsLegacy, radioButtonReturnsUnicode, + radioButtonReturnsLegacy); + } - protected override string DefaultFriendlyName - { - // as the default, make it the same as the table name (w/o extension) - get { return Path.GetFileNameWithoutExtension(ConverterIdentifier); } - } + // this method is called either when the user clicks the "Apply" or "OK" buttons *OR* if she + // tries to switch to the Test or Advanced tab. This is the dialog's one opportunity + // to make sure that the user has correctly configured a legitimate converter. + protected override bool OnApply() + { + Util.DebugWriteLine(this, "BEGIN"); + // Get the converter identifier from the Setup tab controls. + ConverterIdentifier = textBoxFileSpec.Text; + SetConvTypeFromRbControls(radioButtonExpectsUnicode, radioButtonExpectsLegacy, + radioButtonReturnsUnicode, radioButtonReturnsLegacy); + + // if we're actually on the setup tab, then do some further checking as well. + if (tabControl.SelectedTab == tabPageSetup) + { + // only do these message boxes if we're on the Setup tab itself, because if this OnApply + // is being called as a result of the user switching to the Test tab, that code will + // already put up an error message and we don't need two error messages. + if (String.IsNullOrEmpty(ConverterIdentifier)) + { + MessageBox.Show(this, "Choose a Python script first!", EncConverters.cstrCaption); + return false; + } + else if (!File.Exists(ConverterIdentifier)) + { + MessageBox.Show(this, "File doesn't exist!", EncConverters.cstrCaption); + return false; + } + } + Util.DebugWriteLine(this, "END"); + return base.OnApply(); + } - private void buttonBrowse_Click(object sender, EventArgs e) - { - if (!String.IsNullOrEmpty(ConverterIdentifier)) - openFileDialogBrowse.InitialDirectory = Path.GetDirectoryName(ConverterIdentifier); - else - openFileDialogBrowse.InitialDirectory = Util.CommonAppDataPath() + EncConverters.strDefMapsTablesPath; + /* + protected override bool ShouldRemoveBeforeAdd + { + get { return true; } + } + + protected override bool ShouldFriendlyNameBeReadOnly + { + get { return false; } + } + + protected override bool GetFontMapping(string strFriendlyName, out string strLhsFont, out string strRhsFont) + { + return base.GetFontMapping(strFriendlyName, out strLhsFont, out strRhsFont); + } + */ + + protected override string ProgID + { + get { return typeof(PyScriptEncConverter).FullName; } + } - if (openFileDialogBrowse.ShowDialog() == DialogResult.OK) - { - ResetFields(); - textBoxFileSpec.Text = openFileDialogBrowse.FileName; - } - } + protected override string ImplType + { + get { return EncConverters.strTypeSILPyScript; } + } - private void textBoxFileSpec_TextChanged(object sender, EventArgs e) - { - if (m_bInitialized) // but only do this after we're already initialized - { - IsModified = (((TextBox)sender).Text.Length > 0); - //ProcessType &= ~(int)ProcessTypeFlags.SpellingFixerProject; - UpdateUI(IsModified); - } - } + protected override string DefaultFriendlyName + { + // as the default, make it the same as the table name (w/o extension) + get { return Path.GetFileNameWithoutExtension(ConverterIdentifier); } + } -/* - protected override bool SetupTabSelected_MakeSaveInRepositoryVisible - { - get { return !IsSpellFixerProject; } - } + private void buttonBrowse_Click(object sender, EventArgs e) + { + if (!String.IsNullOrEmpty(ConverterIdentifier)) + openFileDialogBrowse.InitialDirectory = Path.GetDirectoryName(ConverterIdentifier); + else + openFileDialogBrowse.InitialDirectory = Util.CommonAppDataPath() + EncConverters.strDefMapsTablesPath; + + if (openFileDialogBrowse.ShowDialog() == DialogResult.OK) + { + ResetFields(); + textBoxFileSpec.Text = openFileDialogBrowse.FileName; + } + } - private void buttonAddSpellFixer_Click(object sender, EventArgs e) - { - try - { - SpellFixerByReflection aSF = new SpellFixerByReflection(); - aSF.LoginProject(); - ((EncConverters)m_aECs).Reinitialize(); - FriendlyName = aSF.SpellFixerEncConverterName; - m_aEC = m_aECs[FriendlyName]; - if (m_aEC != null) - { - textBoxFileSpec.Text = ConverterIdentifier = m_aEC.ConverterIdentifier; - ConversionType = m_aEC.ConversionType; - ProcessType = m_aEC.ProcessType; - UpdateUI(false); - aSF.QueryForSpellingCorrectionIfTableEmpty("incorect"); - aSF.EditSpellingFixes(); - IsInRepository = true; - } - } - catch (Exception) - { - // usually just a "no project selected message, so .... ignoring it - // MessageBox.Show(ex.Message, EncConverters.cstrCaption); - } - } -*/ + private void textBoxFileSpec_TextChanged(object sender, EventArgs e) + { + if (m_bInitialized) // but only do this after we're already initialized + { + IsModified = (((TextBox)sender).Text.Length > 0); + //ProcessType &= ~(int)ProcessTypeFlags.SpellingFixerProject; + UpdateUI(IsModified); + } + } - private void radioButton_CheckedChanged(object sender, EventArgs e) - { - IsModified = true; - } - } + private void radioButton_CheckedChanged(object sender, EventArgs e) + { + IsModified = true; + } + } } diff --git a/src/PyScriptEC/PyScriptEC 2010.csproj b/src/PyScriptEC/PyScriptEC 2010.csproj index dd2a99d2..73408f06 100644 --- a/src/PyScriptEC/PyScriptEC 2010.csproj +++ b/src/PyScriptEC/PyScriptEC 2010.csproj @@ -103,8 +103,14 @@ Form + + PyScriptAutoConfigDialog.cs + + + Form + diff --git a/src/PyScriptEC/PyScriptEncConverter.cs b/src/PyScriptEC/PyScriptEncConverter.cs index e7917cb8..210469a2 100755 --- a/src/PyScriptEC/PyScriptEncConverter.cs +++ b/src/PyScriptEC/PyScriptEncConverter.cs @@ -161,10 +161,10 @@ bool bForward protected unsafe void Load() { Util.DebugWriteLine(this, "BEGIN"); - string strScriptPath = ConverterIdentifier; + string strScriptPath = ConverterIdentifier; - // first make sure it's there and get the last time it was modified - DateTime timeModified = DateTime.Now; // don't care really, but have to initialize it. + // first make sure it's there and get the last time it was modified + DateTime timeModified = DateTime.Now; // don't care really, but have to initialize it. if (!DoesFileExist(strScriptPath, ref timeModified)) EncConverters.ThrowError(ErrStatus.CantOpenReadMap, strScriptPath); diff --git a/src/PyScriptEC/PythonAutoConfigDialog.cs b/src/PyScriptEC/PythonAutoConfigDialog.cs new file mode 100644 index 00000000..58ef62b2 --- /dev/null +++ b/src/PyScriptEC/PythonAutoConfigDialog.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SilEncConverters40 +{ + public class PythonAutoConfigDialog : SilEncConverters40.AutoConfigDialog + { + } +} From 59718a3e487bbe4d1c2f24bb656b93d9eae830af Mon Sep 17 00:00:00 2001 From: bobeaton Date: Thu, 26 Oct 2023 08:00:02 -0500 Subject: [PATCH 002/113] Added Azure Open AI EncConverter -- not free or usable w/o a (currently, hard to get) resource. Underlyingly, this uses chatGPT 3.5 to do translation --- EncConverters 2019.sln | 14 + .../EcTranslators_MergeModule.wxs | 758 +++--- .../EcTranslators_MergeModule.wxs | 758 +++--- .../Translators 4.0.0.0 Plugin Details.xml | 6 + ...ure_OpenAI_Translate_Plug-in_About_box.htm | 2040 +++++++++++++++++ .../colorschememapping.xml | 2 + .../filelist.xml | 15 + .../header.htm | 61 + .../image004.jpg | Bin 0 -> 23751 bytes .../image006.jpg | Bin 0 -> 17638 bytes .../image007.jpg | Bin 0 -> 30485 bytes .../image008.jpg | Bin 0 -> 14551 bytes .../image012.jpg | Bin 0 -> 10254 bytes .../image017.jpg | Bin 0 -> 22096 bytes .../item0013.xml | 1 + .../props014.xml | 2 + .../themedata.thmx | Bin 0 -> 3339 bytes src/ECFileConverter/app.config | 18 +- .../AzureOpenAiAutoConfigDialog.cs | 266 +++ .../AzureOpenAiAutoConfigDialog.designer.cs | 219 ++ .../AzureOpenAiAutoConfigDialog.resx | 126 + .../AzureOpenAi/AzureOpenAiEncConverter.cs | 244 ++ .../AzureOpenAiEncConverterConfig.cs | 65 + .../AzureOpenAi/AzureOpenAiExe/App.config | 50 + .../AzureOpenAiExe/AzureOpenAiExe.csproj | 120 + .../AzureOpenAi/AzureOpenAiExe/Program.cs | 175 ++ .../AzureOpenAiExe/Properties/AssemblyInfo.cs | 36 + .../AzureOpenAiExe/packages.config | 16 + ...reKeyDeploymentNameAndEndpoint.Designer.cs | 196 ++ ...eryForAzureKeyDeploymentNameAndEndpoint.cs | 58 + ...yForAzureKeyDeploymentNameAndEndpoint.resx | 120 + src/EcTranslators/EcTranslators.csproj | 22 +- .../Properties/Resources.Designer.cs | 45 + src/EcTranslators/Properties/Resources.resx | 15 + .../Properties/Settings.Designer.cs | 69 + .../Properties/Settings.settings | 23 + src/EcTranslators/app.config | 42 +- src/EncCnvtrs/EncConverters.cs | 11 +- src/EncCnvtrs/ExeEncConverter.cs | 59 +- src/EncCnvtrs/WebBrowserGecko.cs | 3 +- src/RunTests/app.config | 18 +- src/TestEncCnvtrs/TestEcTranslators.cs | 646 +++--- src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj | 40 +- src/TestEncCnvtrs/app.config | 18 +- src/TestEncCnvtrs/packages.config | 15 +- 45 files changed, 5321 insertions(+), 1071 deletions(-) create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box.htm create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/colorschememapping.xml create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/filelist.xml create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/header.htm create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image004.jpg create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image006.jpg create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image007.jpg create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image008.jpg create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image012.jpg create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image017.jpg create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/item0013.xml create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/props014.xml create mode 100644 redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/themedata.thmx create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.cs create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.designer.cs create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.resx create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverterConfig.cs create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Properties/AssemblyInfo.cs create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config create mode 100644 src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.Designer.cs create mode 100644 src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.cs create mode 100644 src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.resx diff --git a/EncConverters 2019.sln b/EncConverters 2019.sln index 79400fbc..a9bcd64a 100644 --- a/EncConverters 2019.sln +++ b/EncConverters 2019.sln @@ -200,6 +200,8 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "EcTranslators64bitMM", "ins EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackTranslationHelper", "src\BackTranslationHelper\BackTranslationHelper.csproj", "{3E74CE98-6558-4AF0-BB0C-C7E436208B1B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureOpenAiExe", "src\EcTranslators\AzureOpenAi\AzureOpenAiExe\AzureOpenAiExe.csproj", "{4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -618,6 +620,18 @@ Global {3E74CE98-6558-4AF0-BB0C-C7E436208B1B}.Template|Win32.Build.0 = Debug|x86 {3E74CE98-6558-4AF0-BB0C-C7E436208B1B}.Template|x64.ActiveCfg = Debug|x64 {3E74CE98-6558-4AF0-BB0C-C7E436208B1B}.Template|x64.Build.0 = Debug|x64 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Debug|Win32.ActiveCfg = Debug|x86 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Debug|Win32.Build.0 = Debug|x86 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Debug|x64.ActiveCfg = Debug|x64 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Debug|x64.Build.0 = Debug|x64 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Release|Win32.ActiveCfg = Release|x86 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Release|Win32.Build.0 = Release|x86 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Release|x64.ActiveCfg = Release|x64 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Release|x64.Build.0 = Release|x64 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Template|Win32.ActiveCfg = Debug|x86 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Template|Win32.Build.0 = Debug|x86 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Template|x64.ActiveCfg = Debug|x64 + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Template|x64.Build.0 = Debug|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs b/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs index 95178d89..67e563e7 100644 --- a/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs +++ b/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs @@ -2,307 +2,331 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -317,68 +341,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs b/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs index 0b0c5633..dd1ff2d4 100644 --- a/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs +++ b/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs @@ -2,306 +2,330 @@ + Description="Include in any client application deployment project which uses the EncConverters interface" Manufacturer="SIL International" + InstallerVersion="200" Keywords="SIL; Bing Translator; DeepL Translator; Google Translate; EncConverters" /> - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -316,68 +340,90 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml b/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml index 6ba38560..79d029fb 100644 --- a/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml +++ b/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml @@ -18,4 +18,10 @@ DisplayName="Google Translate" ConfiguratorProgId="SilEncConverters40.EcTranslators.GoogleTranslator.GoogleTranslatorEncConverterConfig" AssemblyReference="EcTranslators, Version=4.0.0.0, Culture=neutral, PublicKeyToken=f1447bae1e63f485" /> + diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box.htm b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box.htm new file mode 100644 index 00000000..9c0ab5c8 --- /dev/null +++ b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box.htm @@ -0,0 +1,2040 @@ + + + + + + + + + + + +Azure Open AI Translate + + + + + + + + + + + +
+ +

Azure Open AI Transducer

+ +

This +converter allows you to use Azure Open AI to do text processing within EncConverter-enabled +applications. Azure Open AI is a cloud-based Artificial Intelligence +service based on (currently) Chat GPT 3.5 language model and several other model +types. It can be used to perform language translation and other +language-related operations between a growing number of languages (see this website for specific languages supported). Note that +it requires a live internet connection to function.

+ +

The +Azure Open AI Transducer uses an Azure Open AI Resource to do the +translation, which is available from Microsoft’s Azure portal, and unlike other Translators +supported by the EncConverters core (i.e. Google, +Bing & DeepL), the Azure Open AI Resource +requires you to get your own Azure resource in order to use it. Currently, it +is limited in availability, but it is expected to be offered for general use +shortly.

+ +

See +this website for more information on getting your own Azure +Open AI Resource.

+ +

Setup Tab

+ +

Here is the configuration setup tab for the Azure Open +AI EncConverter:

+ +

+ +

Figure 1: +Azure Open AI Translate Setup 1, 2, 3, 4, 5, 6, +7

+ +

 

+ +

1)      +This text box is for entering the Source +language of the input text for the translation operation.

+ +

2)      This +text box is for entering the Target language the input text should be +translated into.

+ +

3)      This combo box/text box is for choosing one +of the pre-existing additions or entering your own addition to be added to the System +Prompt to customize what is sent to the Azure Open AI service.

+ +

In the example shown +above, the addition tells the AI language model to translate from Hindi to +English and request the result be “in a ‘free translation’ +style aimed at high school students.”

+ +

The underlying language +model is quite good at understanding English and can adjust its translation for +most requests (e.g. even sending the results back in rhyme or in ‘Yoda +speak’ (OSV))

+ +

Click on the drop-down arrow +to the right of the box to see any pre-loaded or previously used additions.

+ +

By default, the System +Prompt used is:

+ +

You will be given 1 or more lines of text in <SourceLanguage> which you are to translate into <TargetLanguage> <additions> and return only the +translated lines.

+ +

This prompt was picked +to allow the converter to work well with the Paratext +Back Translation plug-in, which often has multiple lines (i.e. verses) of text +to be processed and as the language model often returns additional information +about the input line to be translated, by default, it is instructed to return only +the translated text.

+ +

You can override this formatted +System Prompt to get any arbitrary results you want by using the prefix: “UseSystemPrompt: ”

+ +

For example, to see if +it meets the needs of your application, you could start with the simple System Prompt +(which, since the Resource charges by the number of word token used would +result in a lower overall cost):

+ +

UseSystemPrompt: Translate Hindi into English.

+ +

Then, the System Prompt +sent to the language model would simply be:

+ +

Translate Hindi into English.

+ +

Note that if you begin +this field with the string, “UseSystemPrompt: ”, +then the Source and Target language boxes will be ignored.

+ +

Finally, you should +note that the Azure Open AI Resource has Content Filtering +and it may refuse to translate some text if it runs afoul of any of these four +areas: Hate, Sexual, Self-harm, Violence.

+ +

4)      +This box shows the System Prompt that will be sent to +the Azure Open AI service.

+ +

5)      +This button brings up a dialog box into which you can +enter the information needed about your personal Azure Open AI resource (see +below for information).

+ +

Note that unlike the +other Translators supported by EncConverters, the +Azure Open AI (currently) does not have a free pricing tier, and so you must +get your own resource to use it.

+ +

See this +webpage for how to get your own Azure Open AI resource to use for this +transducer.

+ +

6)      If you want the +converter to be permanently added to the System Repository, then you must click +the Save in System Repository button +(see below).

+ +

7)      +You can click on the Test Area tab to test the +converter with some sample data.

+ +
+ +

You may not see script errors until you use the converter to +convert some data. So, for this converter type, it is important to test it +before trying it with real data.

+ +

You can also test various System Prompts in the Azure Open AI +Studio mentioned below to find the specific one you want to use.

+ +
+ +

Entering your own Azure Open AI Resource Information

+ +

Once you acquire your own Azure Open AI resource on the +Azure portal, you can enter the +information to use it in the dialog that appears by clicking the button on the +Setup dialog (5)  above:

+ +

 

+ +

+ +

Figure 2: Entering Azure +Open AI Configuration Data

+ +

 

+ +

The information you need for this dialog (by the number in +red) is available from this page/blade of the Azure portal:

+ +

The value to use in the Enter +Azure Open AI Key’ box (1) above comes from the KEY1 field in Figure 3 below and the value +to use for the Enter Language API Endpoint +box (3) above comes from the Language API +(endpoint) field in Figure 3 below.

+ +

+ +

Figure 3: Azure Portal +Settings for the Azure Open AI Resource

+ +

 

+ +

The value to use in the Deployment +Name field (2) in Figure 2 above comes from the deployment you create on the Deployments blade of the Azure Open AI Studio tool as shown here:

+ +

+ +

Figure 4: Azure Portal +Settings in the Azure OpenAI Studio

+ +

 

+ +

The Azure Open AI Studio +tool can be opened from Model deployments +blade just below the Keys and Endpoint +blade in Figure 3 above.

+ +

Saving the +converter in the System Repository:

+ +

By default, if you click the Apply or OK +buttons, the configured converter will be returned to the client application as +a temporary converter for temporary use. Once the client application (e.g. FieldWorks or Word) is closed or releases the converter, it will no +longer be available. If you want the converter to be permanently available to +client applications, then you must explicitly add it to the System Repository using the Save in System +Repository button.

+ +

When you click this button, the following dialog box will +be displayed to query for a friendly name by +which the converter will be known in client applications:

+ +

 

+ +

+ +

 

+ +

The Advanced Tab can be used to enter further, +optional information about this converter, which is also put into the System Repository and can be used by various client +applications. Click on this tab to display the following dialog box:

+ +

+ +

 

+ +

Though these values are not necessary for the operation of +the converter, they can be helpful to various client applications. For example, +the Clipboard EncConverter +can be configured to filter the list of displayed converters based on the Encoding +Name and/or the Transduction Type configured here.

+ +
+ + + + diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/colorschememapping.xml b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/colorschememapping.xml new file mode 100644 index 00000000..6a0069cd --- /dev/null +++ b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/filelist.xml b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/filelist.xml new file mode 100644 index 00000000..063eb4ce --- /dev/null +++ b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/filelist.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/header.htm b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/header.htm new file mode 100644 index 00000000..865573c5 --- /dev/null +++ b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/header.htm @@ -0,0 +1,61 @@ + + + + + + + + + + + + + +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ + + + diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image004.jpg b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..043fdca1ad1a44429403a2ae51a61b3f2b5f87a3 GIT binary patch literal 23751 zcmeIa1yogC*C@OXARr(mAPv$|N;d~YQt1W}1SF)p#6t)w(j^_zC3WbO?(S{`B&3^v z;}fsX`+UzE|NZ{^k9)rt#vbFWz1LoA&bj8CYu4IVV^?zkwv2?d1OS0R06p*@xS9mS z05lYon<&U=H&Jh*qoZM95n*FtVq%dK+`%QHp`@dwrlh7~VBvefz{t%+Ma}+*om)Ui zL_~z{fy85RVHrNCh|u*Q5Oj2OtXo)Q*w|!3_o(j){o8+6^#BekBntrt5kdtZ;6M;@ zAXiNQ1pq*9fY4q8{OcbC0TJm2G79QVG<2{-2{wQLK}1AALcDPU2?^}&4n7BvaBkq< zWfMidt@s>;$_9_!Gb9<6`eET0e5L*!8V-G1ubXHDcL<4yY3b-0?lE$5ar5x<@rykY zmync_mQhwwRa4i{)G{!9VPtG#`qIwc!O_Xt#ntI+oY47#pk=kr{*&T4<9>0C)V5EeW*-25HfU>M5eFac@kOm9)?%`Z+b2XR_ zNCdHzL=4YHFe2_Y@emMgCd&76#jP_~CQgkFRE({iMn+`I^lKqGiBE~XCAHsTyaLAc zu7Cs_*epT?^agF^jEq63GBj*2g%00^?3U)p!J_d3YH6o+>7jsdUt!a?pcPWGZ^->6 z)>9#>M0R({D8`e1eLbjH^a>E9x&mr%JkNM%sdQxCDDNibSlXcR!rXtWoo~OMLdl&m z>wCZ#c;q@0FO4sWfq=epWLG}1=OhIsO`@_2itM2YboGtyQGLp{0$49<-L|JjZ;o#J zyjyJhJb@FcOr#PiqoI+gmn(wnsj5KUBNKJ`i+J17J~&!W*&PXSNp?miE4~&na{gCv z$iPJ;*2(;xiyekDW{SOr`)70N9P}ToMl?2)2j|KwaQUmm8Ft52Ja-AG6JvLpAJhA- zmWFDw<~@I`FnW(jo#n1cjRafo6U==`-=9aKPg@_wC>^n#nks3~eWa5v8IZsSp|!5Z zP4;FuRh@Raz|siZd{Jo;SuCe_M~TL=z06XD)F5oagXgjn<$UMEJ}-tAdlQ*vI$S2ir_WJAcFdr8AWRvx%6KV5tc+IZI3YXPQJf zxEx3F6mAJZo}7?@-=JYQW2yTAAAW3#*&X8QfwJ)w-*M^y-&MMYJ;?=-DY6zl|=nS&1JiI_JwzYA8wcEycLm8H=Q6zI8}RVYE0AOnyCA zff02)dz4ca8i}zTLVM?8$F70SNthYmenbCWsAiMGiAiDkR~3U8hfktparaDACf^{i z=au7c_PWM+Jg9@$jpM1^KaBWzej#=Rxcl83_Z-#2uN=@5^ohA~>Y;uG0zZ~HY23#M;)2bE3sB4??Vd%ZaXVMlKn?{mED(FD;a-rXlYfqu`!1)xg zgez#$!_TH5b#D5MVQG0$f|qHJL6AIUO#+-5@>s#6rPIbVU2FR3#XyfL;r+9w+sA6= zJXY>G>GAHLv|ivzb=SPWfgCwce%a5fdf!|EFRnN-c)0o%*^Hx6fq$*eJTW$QgrlwX zGuAYP2qW1^=#%w~w#*JCzi(wVvpo~8j-085@aW;?k}}7KnwkqrqC!$_sbO+OQM{2o z6C#^6jSU%gu5p3#HL_t6vYH(X;!4e`qL!(cby`}M*R)x`ca1V)X8KZpmfVLK^ja-)~ASHSGs{oXXYJ2Uh(C4=M7D8C~;pzJmqDY}1DXh7jmE2vvq@u{%S>aE^ zgJt)`sW$a)65$;$O6f~2Qc^LflJ1}&R0#AEK3iePgCBTFKXH?7Dqo72DhC4JjtYI( z5@r~(G*_Bt_Gyo`iEgfTYk#zk^(j=On_yj_$~Lz82bC}8Pe+-qfSYl>R4&9SVXbtl z%6L9Ok@@h#6KhPj+d(#3{JQU;@Di8Yky#u@qPuYflMJ`u2Z~dN-3VNtV)%yOwoDBA zsew(_;?SUNtdU}S`2+Q6UJCQr#3nVCkMAwT_xs@-9agl+?UpDJ!DVot3ixSRWB?9CIwk=MNAfzd+mg}$ri3(C85$3O6G&STYw zq_elflUVWaZ`h8nX5u*%kV(g|@i*4IYEk;)7R*1m!T;5uX#{%EV094*HvvBRG5mL5 zh{4@>v*12kTNi-`8P<#&n@mWo(p^^m?isghSD$GCXfps`sTH7%QC9#~U*8RvT=OlK z6)!iFC11N}1LrU5!izNzIdzz|S;_}D&wXGIB$on`Yiu^uGn3HRO)8%jKW2_`uaf3D zZDGTx8{N&B((_D+S`){E$e=&2a#mv44rgTTk79R))yVJW7udY6JH~{zhS)vNAj>IoN+iI^>z5*;4M>o_mlQ5=vWZlr)rxUv*{kU#<+|<)3q_pOH zS;FNL-^Jc61h5iQmM_}mcmF>>y_umg^Bci7Xk~2L#weU&n`pA74A}(0>`jJ1f zrCs~!a5e)%T10S(-#m@g16hvtfSTA6{zbXMD$lzWa6gS;3l--tXhJ9%qG~2dXy3;) zA5r5>GZ?>ml7gyO9Zc7%-+TgB~O_+qgQb{g&a z$}AF|>c`m2-b?YpOte(Oi1K{%oMRN<)ep#F$%xL@p5CSuBT3e&jvrgiFVSkd0?c+l z`2p#e)oK zT>-7B(1UJRgbeKM*O#R+pJQ}BwI4Mxki_l5jdBy`Pl*8rkg7}st4%iP`DV{8h{D@> z{WPWSDx4xtjSTCXCEa=~R*!hWQ+Ae~?(|qJ+7&AA=^#5Bbo zcBXg6#u`R`68`fIy!sh^i)qqNRr3=KN|*^?#Z=j{4i^aq6`nk{{5bcHfJLHJE>i~` z9je`E))-@k=T^n!%B!6`gh=zYm{>v#wVorb>QYh)(v*;)gyF76o9w2;_ck`J18|&5 zhEg@nRBBe5yCP3WF;l*$n<}p#RZ3)5h6#S|;~v^2LgPbWU{8VizD|ETbh{=n6tqQ74B&1}mwbR(?KBG#uqEkfR zcrwe1U;FgN(w^tR!rP?C3>KA1^w>!C~_ zN@lO<9`V;8vHf&pL#>5g!ca1(LMZpwPE65LJNe5|t5f8cx<`xPs%j9N2Bw&$$wVq} z_J58cEt^1kEj@j|3qlGy^lIN;X}ao}63_5iY)(^0OgwyH+a)pqv=Wk;AS$2f)O{t& zg3Sh9)=*4rUI8NAk1x+*2O9#?qo210ACoFq3#&FUtdX*BsgUSYw4F_J1j%eF&L zxWDNLvZqnn74RB*x(_oeyFlc+fA;+f7|okt_|K#V8~<06SKiclRIbBA{L{#biR1+Kt3F?{{Vn|{QRDIn^V!b@#O4kP>7XhPrNEgcA=6|SD$ zUx76wfAXN)yZE>VotI4fRu_E*p!xa%vAu`7U7+zx4lBAeK4&CmK(K<2!#FPSTrN9L z5_d99l5SRC0WZ#bj}`wj%D+aJCoVjv)&j~5pt1D_cKZ|eA)Y+}nQcP%>|4K9;$#u* zHN`pdwQf^(8cP|=V`on4rSAl-N(yi*&C93=lPz&<(ZZuA<3}sH-f`cfF?{ksW5{;m zFY$?MV2W+i555A>c{pPq+os%;$)TH>l`_jVl24@KUwp>AER@ zlUC|cgDk(MA+JO@A6v!?!Zk%Gjs1LuRq~F>$)OVBmBDuz)hQTw zx15`ewVaDix7JujMn+$SQMH`CQ}QQV1;P@;JZwfP^K#0$`^&8{`S3B+xFf%5p+9zx zif>AlNlko)^2{{2$HtH}Y!L4?_Bfm%Zwd26$8g zs?I3^yZwa{?QM%hjbvAd$8ZOq_)9-OD`3au9+em&uvpnD zE){ku4;%NHlON7(bTE!I9w{bI61(HsJXQ=phvw^;3HXonP3CuOoYg<3 zMhrxxhz+tlD0ihu6DLc9(?nU!`$x_=N+4^WO<~p^-23`Eynf04Y}|lAEsMbyTAcgV zGH&$7`;af4_tEs(-){6F|TlhPP zg_*e|N;XPTQi|%AU~CvmR47hyTtHhM!<1B+tV>blun{pqo^M-HgyYk9i(t2CBltx_ zu)g@4n|!DbY#jqNj&dp`Dy(46eUJ4!ik_??rDJ1zB$p=GRS|6lGL-J5$6FcQrCUxL z!%x@L)U34oa)|%BS90(h?u}Bx7d(?5Hhm z?`?|WDwaelf_n_s$s)zYF2iqqlujD^Gr`9S|9J#b?0*h5?u9-IxdL*;pL)lqkVnwR z2@$7+ln-u1gQPVJ`>B%y|C(jtS!GI%qBkZH-tf<=nHT64HMms*$~&TNZ+LmrA2sRY=uy; zsQnm<5Nh)fR$HNeNQ*Y~p+0^yS<|TR2qh;=Y=Ewm*(eIL@A& z5=Uf=5^Jf5ieL4v@^C!*a+t*;_#{j_r>3NHidXDVqu+_n0Mpt@&jZsg;W*jCnkO^& z{_$gTM_H;y`@R;!lVs%4yJFaUJ=Tqxh%*_9I*6jg@p$bI#ln!sm8bH-)1niUfy$a6=`uRp}G&b z8Q=T9-yDT$Ai8#B0*Qe&{;&$gM{6>>!AbH1igUV3>qse0R>859srBqU-+EeWOk0lq zqa;i}zplZ9wi5IdOBTx{n`)yM3OsikSw#hdI%l%;Kd@-rC2$&#lxM|R{%j<0h+D@a z;%*~iZrQKVyWsXhP+O)UV&KDxc=_IsFSW9J7YpAGqVLV zD>LT@rg!;tQcVe>ddZdCc!qw!#Mu*yJuv-YQ(^ctyFr5~WS6}Sk_7zMRvJvu98U$NgOX5NDe|!ITNHjLx=IuR~LmRlH zI&$BBV|k;`;pKSnC5@*RkNi3J;iLi5$FsW=W0cq#mV`@zD1v>+braVW5@5noKM4Ni z3J_WV!_dvo(~jOgoRSw#G>;6aq>^Hhre_K(x9C_*fNRYjJ1%fgn+CU3=w(|-J2gg} zsIbb}BtX*u%irkA@Ed+=O1<-0%h+1u6P+9$w=eL%F{|5VS(GCMj;9XM_Hn*bw1RIu zckFXXC)_;RCu4`S3L=;wYX3%6$=@L>q^sUJF7z_7-;n1vH3;emoi){&l`^4FXp!?0Si=?xP1~^NtBSUCWr=qhNMVv6Tw}nXP~EHz{a|X z^Mlncq@bYDz*LC0*HuxJz5?_8a$a&fM!g|f^&)i|VE$*)$PRvWscyYJCws@(=xyj781zUmi^JGme{v@*|%jz5<41?IX@CWvN#9;$GmdZ$qI z^CEBGmYa}b50ec&?$>{kEeegQoteOaX1aKcGMr2UJjbdaAwF~uo3Nml#gsckY|Nor z6WN8<(EbWqIYI-X9_Ln9pzhE7%w74>H%@=Ir)N6GH~@ch$I*8J9YOeM0$;PhnPelD zjTs)ly)C+Ly;WfZ#4&OnHv`smO6iFk*%E>|0?oLlFRB0 zMFtG?Ib>X%=Y!OJ>^Tmw~#kWTs#oQ2m_Y4-Lp~eD%9Rxd$t-&p$=cg3U&N z(Gcj*4M6^H(naw*XX<_=8q#DcYXt1PC6xco<>60uYLq9Vt8XeS#0*|RJ^1fI8lmFTg|{XYM4OR#d#)a zfnnWxsL?YviWtcWVa>V%?%txmtd+m?7*6FMvHWAZ52bfVQ5L&_Y6*pN}NGR-@&$ub|bNY>Xc8%Em{%gy<|WX zI75`jAsnC&aJobO)IUvHp#q7VS5Z!fpqsO`Ks8+Cn@&)aQzT1y=~hKAU(UY54H8-M zfezzH{4iEDk6i*4q$MAeEic!F?8o!51{TZ@+NnOgr#78YGu7$GeCSK>Ia!A^(v1g+ z7xsB!=Xk`yock@e>PcRq6YB_L4TRd?FW?oQUh>=1$JAKS#Pc0t9y|uTQ#KjAI2THQNrunfDyQF8LXLmvP69E!B5;^0)C^YKM#!mzJ=SiH2-ZYsjeYW9 zm@p+MWj~3WF?T^jdoMRqPl+p#ASdry`FiaXES(`FwtCB4a*K7ut(Z}EDO-ip+gBtcmzHV2%Lc&GVJfjsV!&P{eI zZCu4#i5^=_F@%i#419Cb$VU0%;yvw7I9s@YuUwY_G(xugG=_&lS%gS;$IrCZ9@pi~ zi4F4;LTVSkipfxQ>a4R=qqKsZ<-o+}cE)(A&4RDhA$Zw(9>~K)8$(MYzKiQ7Q|_{W zq0X^f&+d>I%eUn+4vs{YGE0RFuQXSNC5*t~dppA)$3B&6M@Q)IahERBuWrQoQ*^+~ zD3m3@x629HovG#Ao}*TmlVUeTO;UPbVWeWlVe@YK6(!t(zsnJKw+?Mhq!Ve6Dw5{y zn7ddU6*5x?@w6092g&%AfIH-qICHF$L)?omos63ot^@0*`02$q7-e^GGyQQ2iA11* z>`(-bna^9o=>e@neFuo-P>e>Fp5W&pn{=Ov93afV306kzcrW!BMIKuxTz8TJ* z$Y{7*j_RX~1fY3HuV%F$<(&OW-w(!f)51OT^mpt8->olRXa#*FoL7O_+YJq_>;%TM zH=nKIKFltxLV5+MD!zvz5M=d4zvSo_WD$HyJit5_9y^R{_g5i2b(HO(S*zNlyYLdmZSgebh)I8t_-v)x6I zgB`WAr8C~sF=B~49kp@9wC%MX)rfahwx{q^E`g*EU`@xDvVM?&pVB5$xB@R*#Kn4e6`uA?1ZJZ2S`~n_Oyh498x|h-=zn#CT z`YXN&y-|s?x;;T`(Av6qwO?qMgf6TPbBFN@HeH@xI%xko3-ihQi-Ys8|7$~f?XEMq z8ApsoJi)~#5ORZb^IVT^r7S|aIW>WQnQZFr^jxq^%`l3_Op=!4*lt}2i_1*5T)W$K zcY!lX!eUXu&_7+uAfcqNrmh;skIuF(orKZ-k3-^#nPAHJs0w<#3l{GE?xl`{UTQ$y zh25{g@E>{Q>)i5xeFg7BWdNT0M<4f6z!D-C82@749eLl5ZdT3|8$0`GPfuvAdlNqW zu{GbRJCoeZY@@oe%Y)XJyW8V%g5?5vqIF)uK;EQVo1GWS=U=DlW^{WBmf$;6YTu`% z$%-1Oim5}#?n-D}0>s@zTlOSG1Oo2DGs|VqOWP!7ZeAwl0S=QN&pJ=~D`3@i@pgHb zo&+VVu|lahGRYV(KD;_BKE{miDp0;2P!) z%!a|nnDi^4pwWuE9^C?yR|rc;vOM#fIlL;o)+~>aNz{}>VsdG^USaY*3Zl0N8S?Vw z?xnq@?)LrFr{_24-Jd-ixqBb#XOc}TDP6T5_PS#l4~to%IYxpJv!6%S1p8cgubgm6gz z*7a->*AqMRh|CbgH!x1T=Z<82{M?#dVk^2;$W;9jM{T!&rS8=vHuhXttAeWonaz*_ ziuez@l3bH`R49wycR!hN>I)D}#qOfZM-Rl=^u^gIKCC3@=GD;{JD zyZyAH1C2>AgXxz9rNQ!Km4(kEpQ#vnCrB=<%8vRpZ-_6C!O@AU77teE)qvP z_-p>gNEK$2K^R(VE$a*{EA)4%8@-yWMYn2PL)3*k=ZD~aE6yyR0>zD#x}+Msw1eFM zS-|oqGIdtZ5Cy52NmG^rR3VhiqWU)Q#SBY%(m~6uR~#0GyB7)L={PQ*$hv!pTIO4< z`9a?!=O=c`Ww5B`5lVU5ieKSFD$yktkZTQ4?oGY69}Q~w-n&#e@t(brf(OZ%PY6Zq zpc%0GY34BUu;eEil4gkb;=!I(K9-^zv&fn61?e7wa#_GE1&I`KZn4Fp&fM4#A*1_= zm%eq*m&5mKv^ADJ(=}}UPB5AWsG3qTehOK--8c>X!HEvL0yrE}%;jz;Qg1OJ_4#0;>^{imrr zViRu(EwO1&YIl+>3BD;Z=X+{B*5hQnlX_AXfk&%(o_Em8as?v(kcRp*o2>r6(@o0l zo(0@FtxCM|od6BdN#b44#jh{LcPid5gtADe#>~E)s{KT)JCU6C-* za#;VA<_gev_7CnX%gt%wxR{=epot`>3w*rnwYB3RlRjVZ#I1#!EsXZixM*+aDCySP zE2srsm~loo2fMaZE};iT6iozm-)fvH_l{1MMz~IoV98`0f_9`JSV5|BenXNjF;hBu zZPtXRxYx>=cB4ok&NHNZm55B5E78t$fj8jOB-x|3!n+~o1M_3~y;aNz!LGM5b~1)| z_(`S#-F5a}+Nlp#(2pyVZwM`-nf4q=69;lkg~?&aUk~qn>JJ?z(+04R;j-K1 z+W>e1XRS9g&7#H3w3eizoChpqlG&3c@_Zz&{c;n)6+yJF7rJ*Oj5`>znHFQO6OxKC z&=6=y8Jc?gNF&tMA^U?_9vzb6>?Z;WV+0Xyp3bi7-Ex%AZX=OF88gj-5*J%WlHRXA zEy&IrVeQU2E)FCt#Spj}y1vR>P@}b2EP)iT-{yrXCq$4|S`@P!q!yE|KN-Mp!w^gBfguVpKdClq7K8Duy8P5Zgd$&5MGmiv$W%vs49dNPSBDmDHu`8c? zeuko%?0oK&W?mRFek?7yZGe--Jn6Vfp8?oxYTB-8<=%<;(BvR7<;6>@ zSyt#T9cNp=igeV&(XBIlThr>+m^g-${6nn6q7-crk=V%&Wr)|I)a9C3mu%f9jZ(1fTEu9YI6@5n-r@6FP ztFohv6@aGCMHW7w8A1ruRDa>-lG$l+Q(EQyj!7Wk-<6=2G+s3FFDHMFu`+$r+bhOg{{5=><7>z28(@!6Bmq<~Mp>`5+C-R1s4 zHNAGKd7E4UW-Jm6>E$lOcxFxsI;&lbPIC!yi-8ewrTk4ZF49~YdQygFDxr(GE{Uvt ztAcw~K%D;D8t-IF(1*84KT&+i!Wbz(Ll_ZKU7)~pU*g=&e_-PHWd}OaAnr+gMD=!M zbiMrjt^L-6g&Y&bb?o)RacPcRDdH99Bk$!xBeWR0X{Ce>H{KgeX;ev&2k_>P$DLAg;;K zlSToJu?)pKKFNC`@srku?gY989cvDa=3%Od_jX%SVBU`U;tz5~$?0i9Sjn8nbRRy*JCMc7nWF z$9UPo?sSiL3soPA)>B;g9a12@MOSwxw!wT)0>QhEI3XWyi@q!06u|IBtt2R9l2N)oNEh5OWW zPz(L7D9e{}W`zgs=9^6YAIFB{spVwpW&Jw%Fh1ax5@tSKF7C7DAMQX=-Us8_B1Y?p zyVwJ;4e*f5*IQa*d4JyqUR{XeDWKGh&uL704*phh=G%KI2-fy RTto@0Q3z5eo& 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 JtKx3v{{lV=4x|78 literal 0 HcmV?d00001 diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image007.jpg b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image007.jpg new file mode 100644 index 0000000000000000000000000000000000000000..35044a68258f3e0d2a8326437428c4948dcbd4ee GIT binary patch literal 30485 zcmeFZ1yEdFwlI2{#vwStB|vaUaMuJ6?iPXtcZWbD0TP01aCZyt7Ti6!1PxAbZC+k(-H%n*Aj^w}6nSs3`4o zNjV8&Sw0a_prLALZV*1w1+``hy*~Qh(-NQ5BePB@VhmRrAF|l#+37->_va)k>^YRM{iz=(C zYijH28ydfMc6Imk_Vo`;OioRIo0*-P|Gu`qvAMPVV`um0$?4ho#pTuY%`dq?0Qfht z{*>&W|Q(*!__4#G^7RI#8%NRF3hD z9LG@~({O%&`tz4)f0OLLCYb+!OR_%&`@3B806G{18$2*JAOf7+;f_%ZgvV9n?kde| zUpp#Naj)5Dy@ITlAnmAe5q;ab-jp)a=s`0R66zNz1vIkD70gTR&@9<3$Z0Fv>TN38 zhq?|%1*A#6r8Ce|aA%=vni<1uijN>~N$AlFK^D0tYHzx86+goXq09?7sOemO9dxM4 zsEDR(e5%7_A(ep9GfN^E(`38vC?yN5)9))9PR-bntpxDizI<*XXgW_%(-mxv>Fcv= z+rJmn*GpBV<(}Pn<7}_f74J`%snvW!bEwg z3z5OlRBC2yH--kUe`T3J0$F?LScFW?BRMn!@K>LqlxT~lzjU9LO;qLvqfA86BdWUnnqEk#+IF5~xl z+uMlRqNY~^8Dz8Z*@tHJX((cBCstLT10D)pbC3DDW?Dx2F- z$Bt~5B}~{(`Ps2f{`o+YR<56=v`bq?y*Dvo)o+HbkYdCyh2ozOCI2Hov5%7~yBl?* zCyJtr3^w2P?ahRm?Ih7uPkoiG80!9TO)8D#+j40kd_%bdqaZ9|iK2XAB~PI;cuwH54%lDhp9JAdh(64!)6W5&(9Iod_3^i%wK zq?KOMh=D}1yj)UUvre?>i!YxpT_ugjKp)n1t{Kh z-92Ld1JLgB01%6Om)C`iSwilR41Si&WcmJ&e?AR;v{1xGJT(VICI9N6lldFi5}t0m z&A-+h3NE}Edve^tGBk*XT^-GBU&O9R1XVXZ^A@8vv*Ht{XYM5fHj+5=BwEQ$J`z_u zvR?86v2WOYax`MPP3qWRvka%$Z1kn+@TYF{3^oN^evWD<-12>HIUS$qR`5|ihgRZ) zZPX{mK=O@9#!}lK1hq;Q^I5xC>s{VR zI;8kZDOsY<{Up&Yp6@VvVj?{l{IMUTwLwR7!Z+GbVhQXvgH~6rUU3D7tjRp7^y3-$ z!DpO;fRtw?w}#|fa>tXWvzw$B^U1>WdHK9_!f8cm27xOBfBEyD>KnNBX{J{fp^$$dnO zTm87#;55DOMzy;5^Zq%#S%Upbx~G!TebgeQHm{d-#SHCRo!L1nKKpldd}8Yz^7%|h zN5?AZz6wst??taN8winMn=y)kEj4|LAg<4xdopX$P+bBGo}+N~Ab#%7|S=sw2KNoQRP-Q&6!DvEF274I0@aBp@VfXllF;3sSy zCjS&EgDHN<=mUWJdfUkjKjQ@(r2qmF*|20%=%XfqvBD1Y_inwXd0F!Ayyg9^vnq^r+!nnczOCPnr zD75-_GzR}E8tbH%6i2+%0Ia4~#pG+1Fa-V~t z3B~eYljeN1cg)Yfv@(Wb8+>d#Bl+|Iz=_ejvqr2-*u>k>kAPzpJ8|7T6?1`>Q_s>+=2= zAgunb)Bf8y{y{IoaQw@hJ~E$9)Q-goX7m*A%}a#UjZ34P+r{@Bn5+ zS}Mr|50SK!rZFblIncy+P0qh?R2n8U3T7HrJoQs%O)zf~4Svr@WaO~&t+-=NpLl~W zK&?7v5NMqfTZr*XFQioeSffkwHp;Bop97b%k6e^H{x;*rtVZ~4{Mx2sCY5#vX_}EF z*aod*9h{F(+GyIG6CEh`+(<1dn(s~o)o4%0N*W8CWdVEVYHAX}dmV_AMo8B$*{NA!=oTtHdPuvn+Sv8Qr&V3pWg{3tBHG4;psP zHx(p`^*5?IU+3mNy=0#oK_S`}N%NX|R%YR_&@Hh0xEQ@?lq69TgP;(pl|xRrE>Bki zzH0YzMXx;vE@u%qLdj{E)ok%yaRvLVF4GbAqeaqaMQYM}chU*2z$yk+)K%YnQc`f# zO_EK`f+EBXWaan;Z=O2FDYVSTrFZaPm%+A1j)Y+?X!j7=^z#~Lv}kUt@8p(u_dpYd z6^WaEDHb&i)EMb3ztfJC=wyZnz>SvaRoqs80BW6AYCaj%EqG@%gi36Mbq7Cn*i#@b z4KNUjUe-;{(H};Rv{l}fveX+sr(o1abJp;*x>21UbW94%*6ms_iIr_qyTMIzveL0! zkg%V*$U>>w>@(Fb_lpTw0f=8bQ&xX7&1@TLw0wy2uJ3MRj#40ocTuRS$5P~=g~O%s z0WjA&Yy@SHn-BS(G3|*G6qJO?b@MAETDS<-MK;u+n}qNnoM5npp7+D$=|kk$bo%B4 zD@(_Q1aiTU$(b~Iuw+OvdA=#vx{ib!cro)ymL@_FTS`QikF)kta$(t6hC$WvCLE?g zoUX{#IiQnOakhf>NO@Jx%SgM9vloI@V3bWq8Z8B$q}y|3F;Gl*i}A9()suAX!yr6H zTJuyw7+}mDDK@rfI^eOFsPX5%1jC1}pYRph+OAgl4m+_+VC^2x;(@sEW%Z2}g5cBS z_FO_Fmcva54HqL`R}V|+R85wmSL(HsWm!;ZL}GG)1--n+5CicOJW9CogEdu8z)eyl z$aM!qj)*+Q5iL84pVYAyP+U}P-gbXbVg&~QW@Si1?ir7W8B>yK-g6(1K0Rpc7P-l1 zM;95pEQ)_kRh1xH+tgBDS7VWdV{L&1q?n~mfyyP+>Zh$)(8bqImZ|9n>>?j^PQmEj zgklXouTMgb=2k~HCF&;v!k3q;LAD_S>0L=CaKo+BB)J=T^h<=;ktlp3LBcs2r2w7^ z2V-ajZ22h7zkcCu8?#XFzGy-Wq=nFD!2OF2Q8q|A6+a}N5M4l17u<9p>WqeFlU&+>$UYSUrT-Ag<9wg1W6 zAhp^ytM_(7LB{m$^sj8-P2fCen}`RYb6peEl5ATD5p-|A_tD^XY>=mZD1WuhH~#(p z?WOFLaZ7D=gi@n($|9Qo?oc=pbPu)4%|=&Kb78f=-nI5W4I*#)cw4t8>If;TG)eQhVK95)4h z(wLaIRne5jFv~LjX^@@(D4T3TaC|OdVI@p_`!>~yETxhtH;J!yap>e_H>vOhih$bL zDul6;>&(W_X2WPechi)5A?5VSIrBXD)U`y5aN(4J_uUD{WS%)Ve&(#HTXX6eWp$9% z!XEv%Ilabr5go4W{Q?z}8Dy5z+kspH4?y(_?xUK;gebkzW)7?-WAQeK-7?>Z>rX%Z z=LpzS$iPrkIIjLSAD-YuWBHh%A>Jh#!dKTv08f@J1asQ0xDAl^q{KhT zYu1_j^mEd(2}t5dx|$mM#p_{lA0xH6O)0f+ogF=rtunZ8m@}%^eUrEBCN<;`$j1~g zvyzlu;x4{>q>(0_CR0+j8iGR2^OjpFao4rtjZ<32HrJf8C<}(H0h&H1PqN0!aDrCI zIbqtn8iuL$GW<4v+|H!n3x)h_{8}y6(8Gj*?IBumY4rNN5tLCeeH%Q`pkl6N9h=2u zO?W!qjrBtO+*?|Ppsx)hE3u)Q?z{!1?^s+DE_hT+3wkoS_Q#(*HCiE3BA|{*!ExV+ z(RaZEbq#(elX0Gslc5axp|@D(MwYegDp1j@#2qOl!GGHk(^~vI*lDMZ0gf>KN9X1T zSeW+9At~H*DZa9a5Kv0P@o?u4@+Xx;D8ji8f>CYCK|M>0Uh2OLgL){}Vw zuTSpf=te>fM_&$+_zs3$&y)~_19N2Z^erm~sE3#4;)oQq^17ANeICi@JOI7R#Sef1 zFjiycZunMk1BeNqHzEwWn#0b%!FPb!@I3deom0MeH`aP zTd*t^GAltk>}&!QqUWj=^bTeC^&jYabFIq&I8>8onLTrI zw>_HI(&Xw%jV%^45a1~eL%vNPl;>CZ+2|3-;0+Z&`OsI-2l9RD(Q(J7o9v~!&BSP9?ti5doy zZhSk(J4E8L$Trxy#2&@dm`q>kG4?=xuNm9;g;(eUyf+SXsEOEida22LDb$Q~EmC-!12MomU$^=3&-ta&?krsa+0A#A8R4J#UVA#+ zOa*jS<%Be4M{}l4cQ_3)%YtY;H#B7=2*Bwv(#_#JWt7r-VR8p@MBYu2-Cs__F=T|# z$CM=iwWc!4YcGlJWiryLy`N`I=GZ+UX{Tzqv%!V?Agh=Em)4TMbvQJca zhH-}e43F`o7K?+nQ*Kg{yzu~KiGQ)FZ!KP8_f)boXc*TK@lwz1DMcjdr+JT{;XgWA zjhb@4;GC#0i}H*CE{b%sF{zU0f)g(L+m)}@$+`uwgP1NZ`*?fK_jV>C2i?ioUeLdJ z0f-S6DGPE8jCVt*`A>ZZ`_4(7RJ{}1wznX|kgvY9YHI50N^qfofND|OTr$+h>~7|c z{+0tWI`jY}!5n2kE35ea5AcX8p1Zrz>+&llgb>Dm5xiPpVrSigZ03z&6A=>Kn3r1R zFexPwDZLPfD2}p>oG1eR>zf^G>%0bsDB}1Y&$P~;1toSHO|wsHqL=2MJki|Er?C-9 z*i#>v-}<4*u9#5h8d7%oMap4A;NYEE94{&EWur4vo2AjOS-m(8@O`WyL5izH9^FM4{E7-U56C_y*e8`+4@j! zlOHOm+Ow-9&0XuGy0RmRJFY$f{U(Y!@|g~Z3H_PIF;mK`|JC*-=mBsSqkOZvUM|Eg zL=R_4pXH1C-)u~JY;qq~9)*QB#i6}PtzY$Kq<=gQM`C?Ir*eRMqNqBF@30{q*&JFB z!mb?-0pRcF)eCE6rV`{L9smBKo z*u}mH#Sq#v3VFei8G@XLi!0EFAxDTjIv75v(K(KqSOIYmZ zYeY@&{T$>77PSdflmNso>K}lnXZJUd62f)?f_Ur-pt~xG?s+}34xVB6zPXsT`L>Dj$$>?qooqJ+DhFalyI?tfPi!I^Vg#a z(aTO;-5WD1@F!#S0OR=&pr4oYR{g7Q%4QqCA~VFJ?I>F_H&{*&y;;de$ zDfdn)dJDa7HZ-`bKQ>fKgu(>=0&cN%_((6`B2NaPJ!$R2D_(+uFcMTvYQ_tu^Xt#L zm9Cp2ZEgyPoh4GFbc(v#D*J;w!HWAWSlBTPCnml`IVAi;w;cwe%cr64+6e=sEwc`y zon8Zjuld4cHQYTcBOC$sZ%BO+A+Nrr$BQ(tT#je|#=`_rlAwq!4vjXAnhboPBwz%P z!iHL;Fn_`P%fhRZVAr>w25HvAfxbJS7^($5g{(+M{5BY(L{go#Kd4Un4N>vJc|>Rh zFw&Z*i{&}z2T86EZ;cmfVqFfMW@7q_eg66yW>(@~Muro(VMzNQ2LcLS8?;J1cw^-f z70tu^oyW{C(w<#WT!i$Zp!tb~P@`VoIH!`V=Ai09S^#(kemw=Y3j@ZBPp_va`Z35~BwjThpQbu|pE99@O=(3W~h9(j{j;Ny;Ulo@9iF95$ z97A{n%K?oxY2C$&it*{pm)XI>Ly^(mkDOy++c&L)D4GPVR6#cNloH&yOw=xY-#H#o ztzzOC!Y(8Mu;3+ig|tA;6j=0G$*g{2E% zw!{BEVUH&%B##^I#Gl{S-f7VcKU29AUSp?{aDr>ZJ{!#S6u^TSZGW^s$9KB15SAqF z*S{`jFEIgfxoQPv$_8m!4*|2i%p#}G{)c2YsUKdh+3-d!Hw?Sh=+!9L8ftY zRuyaDnVX}GnCK|Z&YEw8C$F1g2f>Z|FjwBf73|AzEfQP69$J}ile z-)iA|K{M9e;d=xs4R|=OTgds%q|ua}{Cib-qnBkvd7S97H)f$wA^Lh^XAPcJ1M?%OH2^J%u{ga@VR1B==eLx_)Q$U2e0DaLeU@&sU=kimv2yR65p z>H*Rwq1D+)8@%fez?8?GMR~z4C{pSzDG|O51C?)%N!^Q?$vRI~0pckQ{nkwPwHHE_ zJvg-XLnXzLituT(4**r9rJL7uYfsN(r3ZkK?M*)Eb|$Zgvr{(#SR-WEEBTsphs-9C z?kyT|!F4Pad#@X*)3utzZbEMOEd$$0*$P9)qi{!0?35FjBvTqTEeEIi)ozb1E0}dV zS@$cTKi0{YoRsGmcXerauy~z6&NBH0*`kJ)c}uTP#C`3l!H;^JSvbrlW)xM17Zmw? zL{gCqNzkS5NWn(@&NRLoYRX(BMw4RS>^*ttexR^wIj(Kz=3}$Jp{u#9aQ%&~os8}D z&E;r0UZayi&hE2!og{^nq-6Qjg@ADzSpjywgi-F&-IGM)H0x+WIqa{s3UI4%Vuafn zeOsma`pcb69vTDVfUq?OmUKTandlkmME$V&$+58EH)0%&3jVOVn!{B@Fd$J?wOwGS?U~#9okdm&a#kSc^3y&GzqPwF(zZ`aQ z@0&PGlCJY*ty(E-x7oDnaz!10Vh4(p!4$E+jzT>Sqoh9gc*LojQsn3WY|uZDA5B z-Iowzm05FdJY^;2)Z)^0@t}VH*ujQp)o(D69)R+2zWg1}$f-;>)NBh1mr6dOGkja= z3G;bAJoe`uNSV1OQ_?2$JWD0j7fEvl42!>Jv%mT^QThqx_NksIu#7{U_Mt z$0Sg3qbo9$)4%3sRX5Eh6UD5o^m=hR%pL`Dzqd#m?OhXjfF>7iI-@MQ%ZqN4zF-x7mrjXjA z>Dy^80&SY0q59A-^Y{(a)bN+**FJGJREpGV15(HXgzrvAD~b~c>h?S-{fF2IJ5IH@r;Q{%$V7?G1eM^eybEe&=R$)h z579wDTIz}W_DU{|XWY_K>P!sE>3EmLX1H2f!&2|y-q=(E56^AsJd=g^wMT;ObHY&2 zs35ufoke`m&BTZ*jYNuMNujTgk%Ck8qb?U-Jm6#Da_CWIjBmDG>}`N?nkRM|JEPXK zXB*8YdDU8LYy_u>`-l7dMj2KIvbsU)wNX^z5}+; z2#wX5gB4( z#&m2)^@{ayjN&ux>J*7JTl^TZ2S~1VqTNUMgqoD#<24%tMg|?;_7lXK!Ur@7#X5xZ zy9~cT%q`-cqp2`#HXcM?#BPe(Nx^6fUAD<=VEo)5+3%=bI8_37*X`m< zbF?m14?jl`jq}EOnUi0HERb4m*V+}`Ye}w{62~|giA0DLmHtBck(|=W3$D+aU+=OQ z2pu`n(wdD6cHQ$woeB~St=uOE&Ev&$QMQpN({Hy!%p0f5N?Aq5yQ@F37rD^nNh-c_ zK4hl{No*BpJph?KAYQ%0b-Ff~wwzKWQJPlIGT1*8@MD(T$Bf0|CwGKtN@cFYf(k#f zO8fd;8{~<0XTB2)e2$&U1x}m)1N; zNOZm&;rvrLmPw&cn-_T3LnTX0p7g<|D_ot8Kv3%*XHqZdN$(L?i+$lCE3GRW&2z^G zwKY0@wB~6SuP|Ww?CUU^DR@R2sswMpo0M~Hn4eXK?Jh0b-#=J zOSTi|lL2klcuhhTMY_;!z#fTcDj6nB&cl$OW^UpJo+ZLlw!6A`mvM(;2Kp5Z0jSx$BF zC|JNTthNZA8xIoeOcZpdyLO9CE~n;%F}~$uLI^A`+?f z``e3(xcD@Teph}ZrOIZfi*-fDT^TRje%AZ${6K~^*XP44ehcQ(T0P*^$B0ZmMIMZZHY{ypL}t6q)ZOgj_e$L7e@+}t&K_C zGB(-a5}$^c$R$xm5Ru_=#P($Fv)@VjbiHso!L#0A6+hhRKN@ouoN}<#`N)>Yj4!v( zs=^~AgH*-`CiC<>!vpc_uLxyVF3^9L`+}s=vuGxqKUv3xW9j*cU?qPa^g%g@X4M4F z!7pYdS9Zp2e5LxesC#I=26o+2`_W_rpYZ2`jmBxJw6|K1&BwkV;}sgFCm_v`?dTy& z74Ayl^}hiva<~wl-N!b?&TKGI#;#`Sn@z^GpKH{>yBn z%At(mU#qtwsy1s|dR>gdMk;IF9HpEv`c&UO#lUdGL89<0q@F(5Or=tf<*3E0e1q*T zHk#Qj?~p&g#Otvt^+v3p^k)i$LrK^CTkS-3@~d!@Q;;=~Ukj{&cX+z}7J6Pg?19j4@Qm}x+h{zCsLfREQwq!aRb>f4$z3`ymyrl#8~ zJ9H&&6ysCucV9_B(%X^z+hcFsI7>YW-uG7__@axOAyNCC6Y||LDTHVcrJH%Vajo|{ z*i>Q_SBi%6;IO+>`yHf2^i) zRqEgUNFK|Bg&Nlfz>U;LZTCNBLg4`nUyM6co&WgcZ#mQ4Plr%0d^v)pI}16(%rj*P zF$u4|3RCMzb`FHSYLx{&??UtsNYRk#R-dc$8#T}HWW++$7mj*el}PlZzE}Ip+4HFu z#`qr-`dD$KRyJc!GLNcV5zCi0PdP5H?>^*C8wRg$!V@MG85n(;V-Mo!U|Nw#rXb&{TyBzi#a;vwVd1 zsd%dk8Y|Yxkb6ncd=f$6J8B^GHw0dpTp5_Fm~RZkMIG&zMhaO){%~petN(7 z3agfvW}WbSPq{l&yUX;6erUr=L;r}h$Sr+7YlLlWWjnb_Wu#U@|2hELX~zRji*-;m z*yw5cH>3F(Is~CwHi0=&uXG?$G*=7kqF1r2nziuM;9CDZv5C=}br#Y&6a4sHGR z-$^W}^L%P#AEAyQzc(-S>(%qTfiznV=Z0#$Hj6d5e2-hdO-Q)r%RDWw2o;-zG->Sq zu^KYaZ787PGG|;9nmm8n!~g>_QbBH+SvQn1z0=P8i*7GZ8e#OlBwK`HsfBDxQNN@> z;&dUgvQvDoOocZB3Bj0V3g*Yl4PVY%M@3PhBJEZx%Ws2?-n6_y2W@P$Hy6B zwkF_11s%&=ITj)?xe zB9Qj8uunheXIuRnV5NQT@pd>boKHJQX&)~De5n!ypeBMbWtiCfA*^86XBpWra2Gs1 z#6K|5*FS>Mg^_2NQnn}gt$S1pvR3~$qE!NRkgD=m2xhT z>PcOMK={&D^HI!@Dj8)q(G2bj()EaU;I#I$HD7*yrc`~OJNhLfty*sOo>jKKQFxO# zxHDz+$+}Z(zIC&4xo{$p)PARcoY@#|9hoDCC>cKf=x)MIGY>P%lcy#%Akhf>aO3)o zv{lgL&Yp5@Ly=uHZ;70>s9QfSdTOZF8?S=i+bPh5vR?P-$8y8dh5grhG6T&O_4__5 zLXP}rg(SMupJb^g)y1XT5z!TpY=zwUE-x}L!b7$pwdckH689+?Me81qf&?xO!DT{i zq|?LXH#diCtFL>g)Ya&-xJge4H_nOhK&7zoBIs9B=MuR_l7}AX7A2+M1?0iWBUI!?@~1pXP^Jg`M>-8fB$Uhe(k=lK6x;7nMRUC=m#_n`^8LN zSyhGA^^}I%0&7JaDzgK%k8|;Ixw7{s?-FtK>3|QoDR3i<_k264-*c8WNeRU zP$%foy%~k7z4I>R8?@y>Ta}1U}zHwv&Bgy-OgY-1ki6-fz)7@@4RSeG6Rsc4y~- zqZBA%ep#vY0dYRe!%;qYgMK#Rso~G{*VkxmUN574q-0`}BWEvY7;&0RH=e-@P!H=G zCAA&zMfuD}h#7izSAa(B*pGhuZqI?Xv%!s?S2!!@mj+0)xzXU?!}|Vic2k3q@IYlS znw@|KLqUjvKquhQR=1$3jB0EjQp&Tb_53~2u=JXU>#dbsir>WRT_7kKb^bF_gz;9 z5Rr052R>g5VEF)_hzq7WO6x^BU-RWED9L^rz3u#gds~EWoeaW=9xobcA}U6CxBaF6 zo-gB(4inQ*rO3%R|N2onY*S`6$I)g3nTYEWUXSu^_&9@#B}`GQlL>z#8RK^|71e9U zXcvK=PyHkeFdtVF9woSh{9K1}dZ#@*d;r#a@66%u@n7u!gt$EbKgv5&id+ZBkqNmA$N@>Qh5nKeL}=h$jxPzb z=Z#;t%h=aj^V8S8Pv5EJvg+#X3)4XQvY*|%L|o6vBi(uRLVrNjw=O3YdA^n`_MJ$x z*2cRsyF+x&K8UO@i(E>bl<{>&S7$FkQFc#HS1sh45;k#)MfY=MNwEW@zp&G*zwmv| zko2tziMLR*GHgHSoStFfvAKFwcTg2@ zqmearkXO$pL1|PpG{nz3!I3_aEpOX>nm8>fjS$4)7Y%uR211_rj!g(1XhQBm9<_#0 zS#plEs7N`OxAE_HkisgaW`=c$r=#dD+gL$M0aMXz;Vo5XTdB0=#u!VN^gPZ-X%2Tk zzLbeJnlOab7Ch%ZJ5Z6b+Q^Vzo6n{JO{Q5KlxVSXIHnXB&P00p2!``dbQEhZ4sS}Z zZZB0o%1@8wma0YG@+H}nxu2AZqq~%Uo#jh^tpaf#|MiPzK?bU@TKW>#qYdj?)yFD` zojP&A)v&eP=6t3->TJzwS@c^TL0_%@I@mVqb<1k3wF{NWdMoZE!uiJV) zjaJ^m4oV}@VqR~;)^9mfdiw9grRHa#iLlzL4H)5pf9l4+40G1$ek<%eJg7ea>H%40 zg1J^OBc$zY6gHFSuEsB5o>Ly=@>-;)vh6SI|8<<2Z=bb60mnBmtHa<573SxJ8Pt^D zbHFB8KWu`PLUz*cp^86C%C9tq$zcwbw#d;bOvt}>&okk{BbXSZ|L&0A=gYr4#L2dk5X=XG+yw(qD)d~ecO><88J2n_U6TAQA}4*tV*fW;qv)AukR z9;WZD^3{3OA6a-Mj2P`Xd*&aeY&g+|izc3&~WG*6AUfx0%tBQx&df=K8&W>v=2XZYx?HUaA zN@2@!g;C>ExL6Rqqh6`@gm?5^2#{@w60?s5c@kszgc59`&`Mhi)9 zc~FJHe@5+FamPGDce(5@AeMVd!;!HN>0{i(4^{Js7yX+f()-I1$zX<+M~TbPQX+{f zu$_{xQ=jGF%yDz~1q(Qwk~>YFW<0WFq8qNDq+ok4O1&k7(thurF=zy$ec9fB+gs5A zyMqDH51KSAQ9Wv^IwfbDImzfZK|vV9k``h6TRHx8R%P=b^_|5Gh5L=!wUcOc{|D3` za>f*F+kz1zzA!f@ish3r&XW-sbw_&R3~$2nNo(JUwCUA!38SS@mGDn<{B4pbp2*U z`f;fkvklWr8da*$Sfohd*er=B(uP4hM@q^etz^q5*OPE1#r{~fEOiJUg|B&cRA358 z2*tQj!^F70P~vuO)Ih;gqlJ?{T9h(s3X+}+NLks|enE~o^q0Qqr@NW@mE^EtPL_de!_RZa$6v7QuNTG_{D8%9Zoa0%@!Uj`$)>r0W# zv20w(C@jU%8mOPc3<4rieh8VvrOmZ%FTyM$@vy2tAHtId=K`t=Ja@P0w?C9?e|xz& z(3cX2-4jzs2gv>Xr)=w$(?iHnrpEHi2$CgDLG+ZjsiJtbFvTmp4ZXp$Nrrll-k&iZ z;DO|Rhm@p+**Q+Iz;H;D1fbgW0GzhNXd8tp!fZ^;`wK=`#k3+Wth^cg3xrMN?pWk< zwm4P^LGX6~`afTR{mTO0&))#D|9qq2e-ctcox=o|q8|z0#%^LEozZESdt`Az()eo;W@GV~dJ?0Qjjic$HuI&U z!bD1QNQY=UD))woqf=c&w}uVsP8KXCB@G@Pw57Hn@jUAvwjCEAb7M1}G^?9lJ?Z3X z#98=65#?h|xt*3>XBpNk!XNph0b7#xl=}&_2nXrq_7+8)or)5I7n(uETrY~ve)g7; z;*eLGntwHGQ=~bz*w3tJ_2s#yxOPPyZzl$ZLwKBPRr!>R8*#1dhyET#y%3;; z^Ik&9NYqCIBtH~vNL}U-KPu#D781fjq4ZJCJBPERxH&O>tG$O~VVAD}BQr0^WhI8> z!vYa3HGI-X6)&*B@D{toakXr9Q;T6E)F#}3*}DF^VH&Ea@O$aKw0wN< z4^8_%`M9rL5wu&Vt|=y~CK#RpBc8^&EKNE~NYDK{kl|Cp9g>n^Q7G6h0D8?Nui%l_ zRmqq+@7A}sm68(GI~e8Ht1#_3^7W7;E?zg@bOVo_1E^nhnhIDcEbxKFwEn(XOb@Yp z=cf0c#`%Kt6&&-0Kzm6wwqf|y=G)9gAg+W9_qK+cq+ek$5miwVP7R*lHlbTVgT;G! zzAr9k*{f|MRH$RG!ZoE)gXyY&16}quX z@oKH+Y`n%yIWgs0p zG%OgFV*1LRXm@)afCKhH3wm;s#LkMZ-=F7TmMdRPn=^B{APf(FG?7rz?m%XrTThb| z8-1rKCP5V{W>qX0{I1*0W>H1Vmz@V-n|il+W0V~%KaE8rFWiMO=j@Og=m$7NI;7k@ z04z83U@2p%^VkLs4EoxuD%zX-jbrx{oh_ikwY^mG}5H-jFS7tk(Mx>?mN#Y zfb$KAhML_R@_4Ru=1Xe8li;43#B8UeInD5u?$U#aNl;h@2}>>#+C^GMfj1als0jm& zupPke?gNub2rzh3*0#L>tG7oLEH1ykfQ5zpYv?o3+Zgwt-fbt8+5d+9|GXbW_U8hs znAz#yq7OXP!@=OptbdEha+uu?gpC;4!Xy@yC^Qz0~)w`7{e7Dt#u?lQ)c4`U^@spEmX>^`XWo zISRi<866P5l`taH!`G{zs9?|J8PYYo9lfnu+cimGf?Y8C({GDs zK*-%lrhTW|u7^}IOB`+0meO9H0XWC2{tu^_)&Gn2EWe7u`W3NtZ6C4AAT;}hatL$x z`-9q%sH54UhGmy2C-LBBD$p~1oZ5*-yfKl&n~5_W^35lD_Q>`faM}wAh_LUzf2JHE zpmEKG4j)6e?6?=JGBu5P2OSk;Mx6S$my6@|KW;}j?#$Rc8ZKe0h&e#;br_fC?HHw| z!9K^g9oVre$!rMIR#C$My8z!*waqa(h9-0p^}CXX+AF`&tc6b% z`r$F++jN4LW8`hQXf8}(Wm``I|Iu#zf8iSMoI8p|EHu&$ebrGa&r9vwDN5GpPgw0d z*E5~xAUe{t8dUC>xNaL;lf_+CF(;=4<;^!VPca!CZoe)E(D9xX!2ZsKHO*a_`lFcn zWi;Vki8S4Ups{dGorKnqOigiAfufb2CB>kifC*+}S9tpV&+~#A{d$k3_wZt9+z&wP zNe1{j-2F)Rte;9o(>jC*R<^$$E&&+Hm+5txEZJuCP9Z*(0!|$IxAXDq^Bn_rIr_T! z|611fUoYvygPqG#hYo&$DJmwr+q1UsGWQ9FFq>9m<#Gq|wVnY=y@Ep59JDO*rPKb) zwFJhN3QGUGW1rWb%kExhzp$YSVsZ#;ol{wa!Zj8vl}gYF=izNDlwK>X>^EUvpTPc= zs7(%v|CV=x@T+9VhZcNE;EpkR&y_~1(M2-KAHlZi0}@3+4*zu4QcY9U6BRKt6$0vV zk%-rELmSKca}q33nG(vx-N`gKG)-CQ0yIEW4@bH}%g)ELS!pNI@001NV$_tUlc%Gv zREV-A)a7Nzr{`>`nTQXK(|~q9kJ$fFQrgXl@Rcv>oUJbX1VN)MRC|y2;u=NF;+$G2BAd;QFz8`9y!879qvNX1=Lsmy z2ozqkxINy5y;{|B7Ob?f5~%njE18QKp|Av@XGkV(jY(7$bM8QDy*i!9y`4|&_u@G$ zUyk`_QX^ib#eM1QZbINDm33)S(JeL|~*NNEe7gC<=}}!m^z$GjB5Et9G}O4!iNyh`SAZnC0`xnTMbGCSH04O(?d4G2Q zZ=M~ZG0f{CJPs*g<6V@HIh(ub-eabV>ixEQliIRFCup-CwVG_z-Usk6{J-UB(HFnZ zcNKEv@M~CEFEaCHjiKdzb>(wy(miOvYR(12;H~zP1KyJ~!hc%wrcMz3o5#*{u8zFG&xPUXf{&fn8S(UL$z{j-r@KThA z+NpV^*`8XTAst>fF^v(7LAqh8-B64`4?51n#=${&V2G|GuL^Y|-Fxzm$>FD{Qh>rJ zoeup9Iv0Lf@1i4DW4cy6$Y5OXYGAR`mU10t_k&0un2O@S^ooB#l*M6%Vq^W(((j^)67dBheqNYDg@Ey1QH3zDYg%(5U8 z77#Cq*(G4NICmnl@y)CsaN?Dck@Yi-7|(}rA^2hQV!8E5(edRYcLVX-T=DNnCEAq} zmx-z^{>%Me8V6Blt;<}!l6h$QXQ8uFFXgvES-BNE?6zjD+o06gZV`Yd(+L0@pt_20 zI^zM{oZfl4WfTs?#H$f_K%&!|m7ByZG0P-aGj;*hKQ6P$dKS4uaC?pK3P7TuW#|J? z(Jp59!6tuO)dOk*AE>a2pf^U(xb9Rxcv6)dMYs($24?Y$WG*8)dBXY%K^5vBfW{yu zE`4dDM%@P5f@(%}hQY{ob0EY7c$US#&Jp!}j&qKk$3DdzinNMSyXA}62B~qRyEk&b zs^n+izd#jRE;jUuubGzc{>qTd?Y)#nVUVf;sGDn(+_z*mbCAS&B!r~anfnoE$bEZ8 z_=vA4-}6;fC}k#Er}P!$KDcN^E1|?buj){?(IrZiQEqpwF$Oc70pvcMWyb|1dwhz&Ug7P`LLDE?L)peAZI} zcQaJ#VU*Hs<}vR^VXuJr;1>V>Kd$;8t$#Ej?6yoka6#I%vjqZKM)4to;EU4QLbW6; z9d#qWE)gX1DNRMCZD8IX7TZ&m@Rv3(xgg!Pc(Cii&c0l4A}0dn2R1I-DPm+|ew19I z&Jcp*nQNP|p+qjqHNDS{XGlk3E`q`T@?R z!Q57y|CZJKPWf*A)z|?we|RnaPfB#@%9O!%N|!iT;Uv6r?`uTjBLU8Ggn(h7QzDE0 zqk>ZWDsZylAC}?Rs!DKdeD`7o6`wrDJAp+JXA*3KtyG9iEGjRrU6{i>?e}5O=3!+E z1VcTJNgFjEvq??o&v)TvY9G5zt(DU0ug|FbHD-g4@m6iElo}oP;YM@@-kBOyG~RF# zt6&-SjM{QF%`}c{tLKEd$uWj=?-BlX%0WK-yfNnf46D z;q@m&MX%rXXHoy)58SX2_|28j&aKw{#laW(F)5o#CbebCN1jzBk_KIGs`KUP9QBMF z>XWptt~~8Ik(o1*i9M40XO6lbHQkCIaAc4ZaM8ch^k3v{-50ty4435~8|n%-V0zt; z@1Of*qxQ|?Jq)zrdi=-*ss(05cOPK!Z%`0>qsybrlH#2vtxTX6kpfZ#VpRx_j-$oM zsqV;mL1cPyshQb{hu6&7X(A-kdaBhQ4}3udojbBN^s$GAbAh{bR)3s6_&`Rd*_r9! z-wJ9iT_-j|(YEU@Gsn+PTATBE97YrOeZCe!@5ZZfIm|<}JBay6BKUk#v(q)&BX2YI z6EvLYN^IMx%{$&}9{JUKdBo~2MW*NlC8*SA)3iLPhn&N043nN}=0i5N0DqXEA9Qm; zF;wZ|`M$Sl*J44wNaGX=%%U3q;-u_@@}t8qnVV|p<0AqRqoe0+jB-O7x*lIR!=B?9 zeUTaV5?o~+-Nv0e+@p;cAs&z~is^%1Fjr^FY2zau=B+3^6Xbsu*#J{j%9cBz$ zUV|lV@bvGA z_3QpzlknFX=$YEYmw9E#QU0Z13R4zP%?C>3`*q18nKFRVWXL*zZW-I{&T(nBkCj{4 z^P?u{m=DEhnwmIeQ0-UB>}KDc8;SKyqp=*{h$0W58s=;6TL6ggfOo?yg3;6sfZ`gm zm>7bmMz z_{%Kp1$tr`K?|LgZN~u`ZD!)lnrSE#h4hu{d$&#g;DAm|-7`NiTdR#5QG;XsKW`0& zufbxMvRk_OpO~JW(!goc#nh=z@XJ8UEdGUMr2)&X{IG1;oiOun8{nX5W%uhOXJ$r9 z;U%I-aY!potLDQy&OIVQb4DYt%-)sVR@H4LRai@bC^(VE# zqQ4;)KD);~~})6>3Ds*-Zc?t0BavQ{0mRb>pw`)gIl7B)Gxwn10El9%ghoC9LJY1jgK zhf)2fIML6!JIA6w1-y|y3R*P{Y2$5j>ZMz%auQvZxHWP>i2h^zo>x~0%PM3^$Zi`V zca4$=#Ku3gO$7QvV1IsDb}i{n?E51woSrTY_G#7g%upTg?fR9fUCgz^Kf~n9Ly z7w_k{4{H0iKB?!e^L=$mRb=y*rpk7~seyNghv|;yoK!Inh;9?ZY6Q-h7hmIz8~v3u zRkxVa=qEY?^#GX`k1Rge+2#N0Do{#NBvUHQdzdQ3sW)@U<5Strq{$U zLR|iw2;0OV5r%3% zg$3~k!A@YpGkrLBNe;^8h6pNI_WY$tbUY#n(dKQe=w{VrAg>Z1BhKv9`OLnHj%Cz0 zvGG9U(VTHCw&Q6|=fhC)r?S{(jphxpVv9}WQyX2HM*&TgC?k;B-8rC(u+%L#nTDWcQM z@`BtPh7nTo=alTsyf49+%AxP)JF*|g%LyLDj1m_B^2aL!Px|kTDf3I)sA>*eKE2;m zADntz=pC~;9Uw?Ry_@O1RK^3z0Mg45cB6Pd(#i}9^R}ZQTT3kM-7A&~wuuaZY#)ta z-mE>4XZ#Xdp>N8&)zMR$(TPSv_`y!owwAJ3lNU3cCC^T)d0jqldhvt~{=|lWl@Mw@ zq=61)ncbc(!IIHR(oIa}%0W2NY-GCAo&J;+VP!g)G0qVy8blXoRZUu+@??;GaNSia z;&P^>>WUtu2{d?Ah|c}`$mk^^){fOCF!I>7=Jm_fHNe$FL^V)Q{qS8Mzc+#EXbhG+ z?9sf{R_F(!XZge%2;8rs0P@j{=ZLodT*TAC!~KnJ&nowuUVvDR`f)V(H^cc)_XNQP!(})mxtJ2H3A5T7VVx z%3D}Aw-1II?m|u@ zOWfNA&13)t>YCbwZO}?9P`4f)g>(K7tBL(vHR<&q`CuBhoNJAJ!4?-c{XW?$?bDkR zM>Wk~p@p}~a{3fG^I36x;4sUv(R7C#)oSBEQ=Y-MU+#=)8>&jLt&s@COf( zMucOz)6rY`04xNuSeUfWGg!^*Qi~_cvS{BIqk+>J>W}R_1MFFzI^B2`KVPR~LhLAA zTUyI(?L)U#RT&jFPyl53%cL)6>9FUR_4j~T8>@S753OBrX0}zN-=BF_2yk^*GN?fi zvZ$+dbpJ=ZzbYzf4?e|BjIz*CF8+Z+TtA((Rp(qQ zKnn86AlO1SmD|c#hV>~D>%ryLu` zz)W{;(uQ6y>VB#$beJ#-Alrv6mDd(^gss7>Pjne#xX6QBL`V_H%gh?Nh<>XSeL>=U zZoN4#O?;xRz{bjBWkjP*lLvp}qfY;kiU9#8s2Xaso$>yG8ytAq^8I#a6LN!T<+H)| zz5^p}B^3v796Ii_s>Q+;g!{sIpVOfLdp@7Z#%IiZZR9oxVv4NX2DMz^IcGjAnRfjY z*a3DPuS$2(f`5tH%NU`?`TcJpeM*?+L73Xq`6c$eeaSHMFN7w^bI|CcsY&9<{;= zP~?3zA1-c=C9SDCe&I@Vj975F9Es{|%5>_-m$J8XI;oejMC%H*$7h>MaqKJ%Pd?Mh zwrZLxU`}_^0^6-t@6rRF-1S3Oa;oePsxa}RGIf0rpqUz+H;nik=s0)pL$(Ey=Q8fu zhnzbf;wQo6Yt=ds2vudw1M;9AV#Ai`weo`-8Ju=bCD>6EoUi8lRAJu)1V!|9<_Ct1 z>1scVZi&nohiVeH9CF3hy5g;MY4Nl=^e^P_>XjqpYR(hlbXk9%G{Pw4K|Grci`$2A zFUM7pfsyEqPFRIoLYJWzwpni80-X#FXoV9ym$Ep}-{-2kmVhO%o3uVje0l=@tGl4R z0a%qz2&6KZ7?9*-Ds%m2sCC8QlxDlRUF5v6=K3>GAm%5XTPm&#@CdDK*=tpbqeW@) zkuwX?#ux|d9A_=Qz06^4N8aO;QkDp|py{8@#I)sg>%bvSAu&W@dVj*uz=Vuo6*uZa zrZ-ML)U)IeOj7>?g5TfdH-b<*<2LBKqDkL(NkCIki;&6DLD6HO!aga^kNC$+TH5mV zoGYuo@J{-mr?zKSQVB}wZR`|47*LyU8t{nbJqD8~1qVwimP{q&t!BRfV2&|bG zAqD&wh_4Gg{loO#zhX}7nB-@%A%8N;e?G>nbzWkS)c#mgKa};}!GZLF&-#aKXl19H zZoy$qaXp=z1IS(=jmnAx;dd}ldLTLw2%7Jn#dxQE)l!3q8t%C(HEQXySBK6`NSp}u zG!UoB|K%j!>C`EJZ<6-@zo7R1?_7wxrC(y~S|zpkH^=rW}f_8 z_+kP3xQuM8MGluxUpPFBP)IWja&x&WYd4vc+Pj*)C2!PUJ-zOxN(yb2o13v!G-X7t zU8z}K#H`N&J&cAFjFQ~iRRYBy$U(XRzzY;NV`K2FmP?C1)PaIHXoT8p=>{*5%{tW{ z9`xW8$duX!(1q`(Qjn|DzyCN(;il2v(sbGe$*=$(xn^?(=?1uF*tdt(@Ho%|3Px@l zly((x(tuc4*%XZQT?4D>ELMo)51}*pxz&CJqVEf2;KDPTJqcgs`fPkL*#gp>-Yno2 zrec>+*LDyGx6B(ljzv^m@bd0n*Ic_aU@Z56a|YnO-od#-wm<#@PV7Xt literal 0 HcmV?d00001 diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image008.jpg b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image008.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b518a1d40298550ddddce8a305949430645085d8 GIT binary patch literal 14551 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 YFW~>J-#A6lkthGVkNa=9C%&BiZ*o34RsaA1 literal 0 HcmV?d00001 diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image012.jpg b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image012.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2bc4a3f097212d4064ee7b242e488928f8f7ff78 GIT binary patch literal 10254 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image017.jpg b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/image017.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9ec2d0e1888774ce8b91719062a37a2d0fc7ca7a GIT binary patch literal 22096 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/item0013.xml b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/item0013.xml new file mode 100644 index 00000000..df14848b --- /dev/null +++ b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/item0013.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/props014.xml b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/props014.xml new file mode 100644 index 00000000..9621d74e --- /dev/null +++ b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/props014.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/themedata.thmx b/redist/Help/Azure_OpenAI_Translate_Plug-in_About_box_files/themedata.thmx new file mode 100644 index 0000000000000000000000000000000000000000..3d2a4372ca5888704157184c6edc22884c62dae9 GIT binary patch literal 3339 zcmaKu2{hDS8^@B!EXKmY(B4w#{H zw`{ZiMA!fTUe<1l^78bzu}GbwSxtExIayNZ9l$?p^ zjPHCH(%O{)0g;BQi!C>pMwIi~C1N0V*%3u%uKI*eGk9MuF+IE3pkhf|1~Mmn)($@o zHytTM$J`PUIPHk%PG4?((IgFz4%d&#w7>^{^maC?M#STMz_>@0brrVP%KlQ}Tj2+L zuA7eu%*76Z8FtL&|#^J5AnBa+zE$X>3^P__o+?#0e)$t*x z?7L0cw)rqCn$x`f-C?$2tcq-J?*^Ftqh9#I;!mxtI-S}D0C2E&2Oq4vuN>^>8kz9c zl_<{{{UxgTc3-GDg(x8DFNepWBHD9zU{41YvRSOh8RQL!Y@HqiS{Ven|JLz7uw;prX)VZ2_Qe9B?&yCbGe z7UkMbeIy==fzGJXB}iCt;x&gMaC)xb`%^~!DI&DjAcy`*7S41dSK;#Ta6t( z9i6d0KRbl8+xP%cj7N(RS`dI6fnO#_>s+dST~1g9pt6OKo%xi!(V?k{+weEzeAFyM zt_!l+`?zAUJ+Qma7ei!=g-hP)iM*0^XLRy^oCy>lJ-g34uHWTr9{Lv*7gbhE6C13R zp^ATzrP((?ToL!qT21#ekA2XYlaV^Wrt;_H>z19#Cfh5rca8&r9b6VoE7-uPy=U=U}&5r6zGv%?sj@ zvh(e*hRFnlVMvyyL`A7B&C-IDD<~rGs4MT6cJm9hf*!m=KS!m#wU-(ov|i*%UEN&I z$^63bdjo>p5BgCv@`&;kA#UENm5i_dp* zLbM~~b0xnCgCIGvKWUL%I2%!D*qhbsT8MVDC~E4n7xX zj5piuOD;B0u7fD~U$eIYRvki-n>o$|YjoFO(iAr>){p9Fw;w^Y6m4(LHWMuUk~z$8 zXbs}Brduw;j#y{Im$Of+$w+ZU$h)j?Yzb*iX?Ttuecn-~oyVTPCW6kqR&~8jm?+jM zlt15B5Ik^Hc@9MH9Uq$*P_-D)^)C zftTKp3|2SyudZTT3+Xk8eF*&0*V% z3vv$I3Ryu%d%;}YKjcSBn$)5 zo<={H+R7%n`Bktb_ob}v%jD_eM6F{MH7d&qSoZ?32anFdF~F#Q$QyBLeK>PSPPV;2 zy+ZPuONamzw3w`*h8epW73~TmcGp}NYJh%n<7M&{a14#1l5OmdR#@RK#~4n@cYu1J zeE7pUDz7N##;bheM4xO#@VqWBc6yV6F`NlSHtmuydC=XJ!EcQ3RnTvh6F!1me2&fP z|3nWrA1Xcjy_&&t7@S~JK1P3W)>GrFctv8z%Fe^P4z?)G_cDzy9Q_Z-jZ!;V&^Gv8hsRE3&k z_bFJPMZ4r-jQS*PF!P9wu{KOAIa(TaYAmZ2l98SK=uy z=fhpm_r8rI`lp4HrS5_$o4_W|cOjg3*tNZ_m(?`kw-SKM;XHCCg{MLJMBwM!HhC|* zj$>x+>L;!fPi)&^6WU&cIQG@Izt|%f;vuLvU(_A!p@!o4U?7$w7cXJH-EM0B+^%t zFkj&FQ7WgP1J1PNv0%aV^*t!jk+;^*5j`HJ6WilVrRddf9#G$s@%ja)kZE~O^^8sL zsR_T6*l%p1_th4=4hAh(nffdaIO|L2khxw#wZWUf?}(c8*8HS?Xl}jA-ixmmOUNQd z7=}drv$)QTO|HbRO1d&CqNN)K`Vb##;v(9pwIK1R|13JN(Zpm#LVf<}5Vh?J`oi9% zslXGm9gKW~E7NGg=~kHmx4J|P7usR7>LGDQqbm}d0QLMmf)!f=o zR94MkYtS-SHr$56|GjOY?d@_dm|cub+xzIgo;B^YW4{{HB=t2zLs;ZdM8 zf@XP<8)jMt_dONpF351p#k(B8bcvqya2T(j|P; z0Kr$3yB0pOXJ%$Z6w$G7y_8YF3{{(zO-T_U;^pdy;X||VBM%RaHFZnAJ+*0k@^vhS zsGT1X`MIJU#g>gI@7kupWWb%Ymy&D&tnl655P@;Lp zNgFy>;21R*8Jp;P<04NXBSK?{`$y8~f_C4Ef!ea}Ln*tCoN1*Y5j7tpTCvuNUF7eh z$Bb^gQ}!zKR$oOryl$h^$e=KTFQ zVq58kqc~ReudAub{p91Nu8lS6%EUU(`QfE2I&@5}vcjZNO}q2sVEB~(^9IjiQ|Zz@ z0!@{9g|qerVgdtXlB{d&*PB9URdsN!Tc`gmaK3+vgrn2eAbKI57AwTaKFIEMehujf zcXf1WSdgj3uaq_1sOouRueBtAOd}LoxLCE5U}t-IjIWy};kkw-8Dc@S2 zMr~n+fzc^8P!X$$D`rpp+HclSxQSOnMF!mpkrVuUAVKJgJfSMDbuT+@lDQfb^5wI} z2)%DCqvjELnHFNnI~2fN>0l6o6SOF6)zoyqEE@6&#bXtkf>D}2-$)$HKk3RfT1avc z@Naxz^&+644cVf~X)|Ghw*()QK|U#(4romA?{!(e?cbt!aJ^#b6gxT>pD+f(*!RrQ z!~V!1Tz$B_I@a?o%sPecc*g$*uYdE%ZzS>`5Hmi|F3%Uqj0gaFdG$B)Budfl_LdFo zj+|8HI;9CQpI_iAmj%M29baTzC8Xt$crTx%E4Y*j0o7(wu4T4))X&FjS%6GpM%0}u zF%j`z@CAP7L_=v~DTswMOd;LpAk^SNc5m$YweWJ4!UXiBL}3xKi_ojbydIkWHEUPM zD@gMto?t3KFx4z`yJky8D8^Y146^%Sj`SUg+AICAqx=0|S*1pM$hM7*FUMKN{>HCe zY$pK!o6K3)ej9(_bTh+$3hYGHU(xccdj1BkI|Fy3->*PH78C!5fPdrQZ{^>qw3EYr sDGmNf>EBegQ)6cn{L;ud@Xu`iPfM5??q&ZOxR>?WvD~NsWOu;70J8Vy&j0`b literal 0 HcmV?d00001 diff --git a/src/ECFileConverter/app.config b/src/ECFileConverter/app.config index 5f60bbd4..18aae022 100644 --- a/src/ECFileConverter/app.config +++ b/src/ECFileConverter/app.config @@ -17,17 +17,25 @@ + + + + + + + + - + @@ -43,19 +51,19 @@ - + - + - + - + diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.cs new file mode 100644 index 00000000..08c8eaa5 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.cs @@ -0,0 +1,266 @@ +// #define encryptingNewCredentials + +using System; +using System.Windows.Forms; +using ECInterfaces; // for IEncConverter +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using static SilEncConverters40.EcTranslators.AzureOpenAI.AzureOpenAiEncConverter; +using System.Net; +using SilEncConverters40.EcTranslators.Properties; + +namespace SilEncConverters40.EcTranslators.AzureOpenAI +{ + public partial class AzureOpenAiAutoConfigDialog : AutoConfigDialog + { + private const string SourceLanguageNameMustBeConfigured = ""; + private const string TargetLanguageNameMustBeConfigured = ""; + private readonly string ResourceNeededWarning = $"The {AzureOpenAiEncConverter.strDisplayName} requires an Azure OpenAI resource."; + + public AzureOpenAiAutoConfigDialog + ( + IEncConverters aECs, + string strDisplayName, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strLhsEncodingId, + string strRhsEncodingId, + int lProcessTypeFlags, + bool bIsInRepository + ) + { + Util.DebugWriteLine(this, "(1) BEGIN"); + InitializeComponent(); + Util.DebugWriteLine(this, "initialized component"); + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + + base.Initialize + ( + aECs, + strHtmlFilename, + strDisplayName, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strLhsEncodingId, + strRhsEncodingId, + lProcessTypeFlags, + bIsInRepository + ); + Util.DebugWriteLine(this, "called base.Initalize"); + + string fromLanguage = SourceLanguageNameMustBeConfigured, toLanguage = TargetLanguageNameMustBeConfigured; + + // if we're editing converter, then set the Converter Spec and say it's unmodified + if (m_bEditMode) + { + System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(ConverterIdentifier)); + + ParseConverterIdentifier(ConverterIdentifier, out fromLanguage, out toLanguage, + out string addlInstructions, out string systemPrompt); + + textBoxCompleteSystemPrompt.Text = systemPrompt; + if (!String.IsNullOrEmpty(addlInstructions)) + comboBoxSystemPromptAdditions.Text = addlInstructions; + IsModified = false; + } + else + { + textBoxCompleteSystemPrompt.Text = ResourceNeededWarning; + } + + textBoxSourceLanguage.Text = fromLanguage; + textBoxTargetLanguage.Text = toLanguage; + LoadComboBoxFromSettings(comboBoxSystemPromptAdditions, Settings.Default.AzureOpenAiSystemPromptAdditions); + + m_bInitialized = true; + + helpProvider.SetHelpString(textBoxSourceLanguage, Properties.Resources.HelpForAzureOpenAiSourceLanguageTextBox); + helpProvider.SetHelpString(textBoxTargetLanguage, Properties.Resources.HelpForAzureOpenAiTargetLanguageTextBox); + helpProvider.SetHelpString(textBoxCompleteSystemPrompt, Properties.Resources.HelpForAzureOpenAiSystemPromptTextBox); + helpProvider.SetHelpString(comboBoxSystemPromptAdditions, Properties.Resources.HelpForAzureOpenAiSystemPromptAdditionsComboBox); + helpProvider.SetHelpString(buttonSetAzureOpenAiApiKey, Properties.Resources.HelpForAzureOpenAiAddYourOwnApiKey); + + Util.DebugWriteLine(this, "END"); + } + + private void InitializeComboBoxFromCode(ComboBox comboBox, string code) + { + if (String.IsNullOrEmpty(code)) + return; + + string value = $"({code})"; + var item = comboBox.Items.Cast().FirstOrDefault(i => i.Contains(value)); + + if ((item == null) && (comboBox.Items.Count > 0)) + { + item = (string)comboBox.Items[0]; + } + + if (item != null) + comboBox.SelectedItem = item; + } + + public AzureOpenAiAutoConfigDialog + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + Util.DebugWriteLine(this, "(2) BEGIN"); + InitializeComponent(); + + base.Initialize + ( + aECs, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strTestData + ); + Util.DebugWriteLine(this, "END"); + } + + // this method is called either when the user clicks the "Apply" or "OK" buttons *OR* if she + // tries to switch to the Test or Advanced tab. This is the dialog's one opportunity + // to make sure that the user has correctly configured a legitimate converter. + protected override bool OnApply() + { + if (!IsModified) + return true; + + var azureOpenAiResourceKey = AzureOpenAiKeyOverride; + var azureOpenAiEndpoint = AzureOpenAiEndpoint; + var azureOpenAiDeploymentName = AzureOpenAiDeploymentName; + if (String.IsNullOrEmpty(azureOpenAiResourceKey) || String.IsNullOrEmpty(azureOpenAiEndpoint) || String.IsNullOrEmpty(azureOpenAiDeploymentName)) + { + MessageBox.Show(this, $"Click the '{buttonSetAzureOpenAiApiKey.Text}' button to enter your Azure Open AI Resource information", EncConverters.cstrCaption); + return false; + } + + var additionToSystemPrompt = comboBoxSystemPromptAdditions.Text?.Trim().Replace(";", null); + if (!String.IsNullOrEmpty(additionToSystemPrompt) && !Settings.Default.AzureOpenAiSystemPromptAdditions.Contains(additionToSystemPrompt)) + { + Settings.Default.AzureOpenAiSystemPromptAdditions.Insert(0, additionToSystemPrompt); + Settings.Default.Save(); + } + + var selectedFromLanguage = textBoxSourceLanguage.Text; + var selectedToLanguage = textBoxTargetLanguage.Text; + if (!additionToSystemPrompt.StartsWith(ReplacementSystemPrompt)) + { + if (!IsValidUserInput(SourceLanguageNameMustBeConfigured, ref selectedFromLanguage)) + { + MessageBox.Show(this, "A Source language name (e.g. Hindi) must be entered and cannot contain a ';' character!", EncConverters.cstrCaption); + return false; + } + + if (!IsValidUserInput(TargetLanguageNameMustBeConfigured, ref selectedToLanguage)) + { + MessageBox.Show(this, "A Target Language (e.g. English) must be entered and cannot contain a ';' character!", EncConverters.cstrCaption); + return false; + } + } + else + { + selectedFromLanguage = null; + selectedToLanguage = null; + } + + // for Azure Open AI, get the converter identifier from the Setup tab controls. + // e.g. "Hindi;English;with a 'free translation' style aimed at high school students" + ConverterIdentifier = String.Format("{0};{1};{2}", + selectedFromLanguage, + selectedToLanguage, + additionToSystemPrompt); + + return base.OnApply(); + + static bool IsValidUserInput(string defaultValue, ref string userInput) + { + userInput = userInput?.Trim(); + return (defaultValue != userInput) && !String.IsNullOrEmpty(userInput) && !userInput.Contains(";"); + } + } + + protected override string ProgID + { + get + { + return typeof(AzureOpenAiEncConverter).FullName; + } + } + + protected override string ImplType + { + get + { + return EncConverters.strTypeSILAzureOpenAiTranslator; + } + } + + protected override string DefaultFriendlyName + { + // as the default, make it the same as the table name (w/o extension) + get + { + var additionToSystemPrompt = comboBoxSystemPromptAdditions.Text?.Trim().Replace(";", null); + if (additionToSystemPrompt.StartsWith(ReplacementSystemPrompt)) + return $"Azure Open AI {SubstituteSystemPrompt(additionToSystemPrompt)}"; + + var selectedFromLanguage = textBoxSourceLanguage.Text.Trim(); + if (selectedFromLanguage == SourceLanguageNameMustBeConfigured) + selectedFromLanguage = null; + var selectedToLanguage = textBoxTargetLanguage.Text.Trim(); + if (selectedToLanguage == TargetLanguageNameMustBeConfigured) + selectedToLanguage = null; + return $"Azure Open AI Translate {selectedFromLanguage} to {selectedToLanguage}"; + } + } + + private void textBox_TextChanged(object sender, EventArgs e) + { + if (m_bInitialized) // but only do this after we've already initialized (we might have set it during m_bEditMode) + IsModified = true; + UpdateSystemPrompt(); + } + + private void comboBoxSystemPromptAdditions_TextChanged(object sender, EventArgs e) + { + if (m_bInitialized) + IsModified = true; + UpdateSystemPrompt(); + } + + private void UpdateSystemPrompt() + { + var systemPrompt = AzureOpenAiEncConverter.GetSystemPrompt(textBoxSourceLanguage.Text?.Trim(), textBoxTargetLanguage.Text?.Trim(), + comboBoxSystemPromptAdditions.Text?.Trim()); + textBoxCompleteSystemPrompt.Text = systemPrompt; + } + + private void ButtonSetAzureOpenAiKey_Click(object sender, EventArgs e) + { +#if encryptingNewCredentials + var azureOpenAiKeyHide = "5bc..."; + var clientId = EncryptionClass.Encrypt(azureOpenAiKeyHide); +#endif + + using var dlg = new QueryForAzureKeyDeploymentNameAndEndpoint(AzureOpenAiKeyOverride, AzureOpenAiDeploymentName, + AzureOpenAiEndpoint); + if (dlg.ShowDialog() == DialogResult.OK) + { + AzureOpenAiKeyOverride = dlg.AzureOpenAiKeyOverride; + AzureOpenAiDeploymentName = dlg.AzureOpenAiDeploymentName; + AzureOpenAiEndpoint = dlg.AzureOpenAiEndpoint; + Properties.Settings.Default.Save(); + } + } + } +} + diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.designer.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.designer.cs new file mode 100644 index 00000000..49dd4288 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.designer.cs @@ -0,0 +1,219 @@ +using System; +using ECInterfaces; // for Util + +namespace SilEncConverters40.EcTranslators.AzureOpenAI +{ + partial class AzureOpenAiAutoConfigDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelSourceLanguage = new System.Windows.Forms.Label(); + this.labelTargetLanguage = new System.Windows.Forms.Label(); + this.labelSystemPromptAddition = new System.Windows.Forms.Label(); + this.comboBoxSystemPromptAdditions = new System.Windows.Forms.ComboBox(); + this.buttonSetAzureOpenAiApiKey = new System.Windows.Forms.Button(); + this.textBoxSourceLanguage = new System.Windows.Forms.TextBox(); + this.textBoxTargetLanguage = new System.Windows.Forms.TextBox(); + this.labelSystemPrompt = new System.Windows.Forms.Label(); + this.textBoxCompleteSystemPrompt = new System.Windows.Forms.TextBox(); + this.tabControl.SuspendLayout(); + this.tabPageSetup.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tabPageSetup + // + this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); + // + // buttonApply + // + this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonApply, true); + // + // buttonCancel + // + this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); + this.helpProvider.SetShowHelp(this.buttonCancel, true); + // + // buttonOK + // + this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonOK, true); + // + // buttonSaveInRepository + // + this.helpProvider.SetHelpString(this.buttonSaveInRepository, "\r\nClick to add this converter to the system repository permanently.\r\n "); + this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.labelSourceLanguage, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.labelTargetLanguage, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.labelSystemPromptAddition, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.comboBoxSystemPromptAdditions, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.buttonSetAzureOpenAiApiKey, 1, 4); + this.tableLayoutPanel1.Controls.Add(this.textBoxSourceLanguage, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxTargetLanguage, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.labelSystemPrompt, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.textBoxCompleteSystemPrompt, 1, 3); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); + this.tableLayoutPanel1.TabIndex = 1; + // + // labelSourceLanguage + // + this.labelSourceLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelSourceLanguage.AutoSize = true; + this.labelSourceLanguage.Location = new System.Drawing.Point(47, 18); + this.labelSourceLanguage.Name = "labelSourceLanguage"; + this.labelSourceLanguage.Size = new System.Drawing.Size(91, 13); + this.labelSourceLanguage.TabIndex = 6; + this.labelSourceLanguage.Text = "Source language:"; + // + // labelTargetLanguage + // + this.labelTargetLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelTargetLanguage.AutoSize = true; + this.labelTargetLanguage.Location = new System.Drawing.Point(50, 68); + this.labelTargetLanguage.Name = "labelTargetLanguage"; + this.labelTargetLanguage.Size = new System.Drawing.Size(88, 13); + this.labelTargetLanguage.TabIndex = 8; + this.labelTargetLanguage.Text = "Target language:"; + // + // labelSystemPromptAddition + // + this.labelSystemPromptAddition.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelSystemPromptAddition.AutoSize = true; + this.labelSystemPromptAddition.Location = new System.Drawing.Point(3, 118); + this.labelSystemPromptAddition.Name = "labelSystemPromptAddition"; + this.labelSystemPromptAddition.Size = new System.Drawing.Size(135, 13); + this.labelSystemPromptAddition.TabIndex = 12; + this.labelSystemPromptAddition.Text = "Additions to system prompt:"; + // + // comboBoxSystemPromptAdditions + // + this.comboBoxSystemPromptAdditions.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.comboBoxSystemPromptAdditions.FormattingEnabled = true; + this.comboBoxSystemPromptAdditions.Location = new System.Drawing.Point(144, 114); + this.comboBoxSystemPromptAdditions.Name = "comboBoxSystemPromptAdditions"; + this.comboBoxSystemPromptAdditions.Size = new System.Drawing.Size(449, 21); + this.comboBoxSystemPromptAdditions.TabIndex = 3; + this.comboBoxSystemPromptAdditions.TextChanged += new System.EventHandler(this.comboBoxSystemPromptAdditions_TextChanged); + // + // buttonSetAzureOpenAiApiKey + // + this.buttonSetAzureOpenAiApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.buttonSetAzureOpenAiApiKey.Location = new System.Drawing.Point(144, 368); + this.buttonSetAzureOpenAiApiKey.Name = "buttonSetAzureOpenAiApiKey"; + this.buttonSetAzureOpenAiApiKey.Size = new System.Drawing.Size(290, 23); + this.buttonSetAzureOpenAiApiKey.TabIndex = 5; + this.buttonSetAzureOpenAiApiKey.Text = "Enter your Azure Open AI Resource Key"; + this.buttonSetAzureOpenAiApiKey.UseVisualStyleBackColor = true; + this.buttonSetAzureOpenAiApiKey.Click += new System.EventHandler(this.ButtonSetAzureOpenAiKey_Click); + // + // textBoxSourceLanguage + // + this.textBoxSourceLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxSourceLanguage.Location = new System.Drawing.Point(144, 15); + this.textBoxSourceLanguage.Name = "textBoxSourceLanguage"; + this.textBoxSourceLanguage.Size = new System.Drawing.Size(449, 20); + this.textBoxSourceLanguage.TabIndex = 1; + this.textBoxSourceLanguage.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // textBoxTargetLanguage + // + this.textBoxTargetLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxTargetLanguage.Location = new System.Drawing.Point(144, 65); + this.textBoxTargetLanguage.Name = "textBoxTargetLanguage"; + this.textBoxTargetLanguage.Size = new System.Drawing.Size(449, 20); + this.textBoxTargetLanguage.TabIndex = 2; + this.textBoxTargetLanguage.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // labelSystemPrompt + // + this.labelSystemPrompt.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelSystemPrompt.AutoSize = true; + this.labelSystemPrompt.Location = new System.Drawing.Point(59, 251); + this.labelSystemPrompt.Name = "labelSystemPrompt"; + this.labelSystemPrompt.Size = new System.Drawing.Size(79, 13); + this.labelSystemPrompt.TabIndex = 12; + this.labelSystemPrompt.Text = "System prompt:"; + // + // textBoxCompleteSystemPrompt + // + this.textBoxCompleteSystemPrompt.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxCompleteSystemPrompt.Location = new System.Drawing.Point(144, 153); + this.textBoxCompleteSystemPrompt.Multiline = true; + this.textBoxCompleteSystemPrompt.Name = "textBoxCompleteSystemPrompt"; + this.textBoxCompleteSystemPrompt.ReadOnly = true; + this.textBoxCompleteSystemPrompt.Size = new System.Drawing.Size(449, 209); + this.textBoxCompleteSystemPrompt.TabIndex = 3; + // + // AzureOpenAiAutoConfigDialog + // + this.ClientSize = new System.Drawing.Size(634, 479); + this.Name = "AzureOpenAiAutoConfigDialog"; + this.Controls.SetChildIndex(this.tabControl, 0); + this.Controls.SetChildIndex(this.buttonApply, 0); + this.Controls.SetChildIndex(this.buttonCancel, 0); + this.Controls.SetChildIndex(this.buttonOK, 0); + this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); + this.tabControl.ResumeLayout(false); + this.tabPageSetup.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label labelSourceLanguage; + private System.Windows.Forms.Label labelTargetLanguage; + private System.Windows.Forms.Label labelSystemPromptAddition; + private System.Windows.Forms.ComboBox comboBoxSystemPromptAdditions; + private System.Windows.Forms.Button buttonSetAzureOpenAiApiKey; + private System.Windows.Forms.TextBox textBoxSourceLanguage; + private System.Windows.Forms.TextBox textBoxTargetLanguage; + private System.Windows.Forms.Label labelSystemPrompt; + private System.Windows.Forms.TextBox textBoxCompleteSystemPrompt; + } +} diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.resx b/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.resx new file mode 100644 index 00000000..a8e879bd --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiAutoConfigDialog.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 341, 17 + + \ No newline at end of file diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs new file mode 100644 index 00000000..28da47fd --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs @@ -0,0 +1,244 @@ +// +// PerlExpressionEncConverter.cs +// +// Created by Jim Kornelsen on Nov 21 2011 +// +// 28-Nov-11 JDK Wrap Perl expression and write in temp file, rather than requiring input file. +// 09-Jan-12 JDK eInFormEngine should be UTF8, but eOutFormEngine UTF16 because it is a C# string. +// +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Text; +using System.Text.RegularExpressions; +using Microsoft.Win32; // for RegistryKey +using ECInterfaces; // for IEncConverter +using SilEncConverters40.EcTranslators.BingTranslator; +using System.Windows.Forms; +using System.Reflection; +using Google.Apis.Discovery; + +namespace SilEncConverters40.EcTranslators.AzureOpenAI +{ + /// + /// Access to ChatGPT 3.5 via Azure's OpenAI + /// + public class AzureOpenAiEncConverter : ExeEncConverter + { + #region Member Variable Definitions + protected string AiSystemInstructions; + + public const string strDisplayName = "Azure OpenAI Translator"; + const string SystemPromptFormat = "You will be given 1 or more lines of text in {0} which you are to translate into {1}{2} and return only the translated lines."; + public static readonly string strHtmlFilename = "Azure_OpenAI_Translate_Plug-in_About_box.htm"; + public const string strExeDefPath = "AzureOpenAiExe"; + public const string ImplTypeSilAzureOpenAi = "SIL.AzureOpenAI"; + public const string ReplacementSystemPrompt = "UseSystemPrompt: "; + + public const string EnvVarNameDeploymentName = "EncConverters_AzureOpenAiDeploymentName"; + public const string EnvVarNameEndPoint = "EncConverters_AzureOpenAiEndpoint"; + public const string EnvVarNameKey = "EncConverters_AzureOpenAiKey"; + + #endregion Member Variable Definitions + + #region Initialization + // by putting the azure key in a settings file, users can (someday) get their own azure OpenAI resource + // and enter their own key in the settings file(s) (or the UI to have us set it in the file) to have + // access to it + public static string AzureOpenAiEndpoint + { + get + { + return Properties.Settings.Default.AzureOpenAiEndpoint; + } + set + { + Properties.Settings.Default.AzureOpenAiEndpoint = value; + } + } + + public static string AzureOpenAiDeploymentName + { + get + { + var deploymentName = Properties.Settings.Default.AzureOpenAiDeploymentName; + return deploymentName; + } + set + { + // the value is already encrypted by the time it gets here + Properties.Settings.Default.AzureOpenAiDeploymentName = value; + } + } + + public static string AzureOpenAiKeyOverride + { + get + { + var overrideKey = Properties.Settings.Default.AzureOpenAiKeyOverride; + return String.IsNullOrEmpty(overrideKey) ? overrideKey : EncryptionClass.Decrypt(overrideKey); + } + set + { + // the value is already encrypted by the time it gets here + var key = String.IsNullOrEmpty(value) ? value : EncryptionClass.Encrypt(value); + Properties.Settings.Default.AzureOpenAiKeyOverride = key; + } + } + + /// + /// The class constructor. + public AzureOpenAiEncConverter() + : base( + typeof(AzureOpenAiEncConverter).FullName, + ImplTypeSilAzureOpenAi, + ConvType.Unicode_to_Unicode, // conversionType + EncConverters.strDefUnicodeEncoding, // lhsEncodingID + EncConverters.strDefUnicodeEncoding, // rhsEncodingID + (Int32)ProcessTypeFlags.Translation, // lProcessType + "") + { + } + + public override void Initialize( + string converterName, + string converterSpec, + ref string lhsEncodingID, + ref string rhsEncodingID, + ref ConvType conversionType, + ref Int32 processTypeFlags, + Int32 codePageInput, + Int32 codePageOutput, + bool bAdding) + { + // let the base class have first stab at it + base.Initialize(converterName, converterSpec, ref lhsEncodingID, ref rhsEncodingID, + ref conversionType, ref processTypeFlags, codePageInput, codePageOutput, bAdding ); + + ParseConverterIdentifier(converterSpec, out string fromLanguage, out string toLanguage, + out string addlInstructions, out string systemPrompt); + + AiSystemInstructions = systemPrompt; + + // this is the only one we support from now on (if the user really wants to do legacy to unicode, they have to deal with the legacy as coming in utf-8 format + conversionType = ConvType.Unicode_to_Unicode; + } + + internal static bool ParseConverterIdentifier(string converterSpec, + out string fromLanguage, out string toLanguage, + out string addlInstructions, out string systemPrompt) + { + var strs = converterSpec.Split(new[] { ';' }); + if (strs.Length < 2) + throw new ApplicationException($"{strDisplayName} not properly configured! converterSpec: {converterSpec} must have at least a source and target language (eg. Hindi;English)"); + + fromLanguage = strs[0]; + toLanguage = strs[1]; + addlInstructions = (strs.Length == 3) + ? strs[2] + : String.Empty; + + systemPrompt = GetSystemPrompt(fromLanguage, toLanguage, addlInstructions); + + return true; + } + + public static string GetSystemPrompt(string fromLanguage, string toLanguage, string addlInstructions) + { + return (addlInstructions.StartsWith(ReplacementSystemPrompt)) + ? SubstituteSystemPrompt(addlInstructions) + : FormatSystemPrompt(fromLanguage, toLanguage, addlInstructions); + } + + public static string SubstituteSystemPrompt(string addlInstructions) + { + return addlInstructions.Substring(ReplacementSystemPrompt.Length).Replace(";", null); + } + + public static string FormatSystemPrompt(string fromLanguage, string toLanguage, string addlInstructions) + { + // can't have double quotes in it, bkz we pass it as a command line parameter surrounded by double quotes + return String.Format(SystemPromptFormat, fromLanguage, toLanguage, $" {addlInstructions.Replace(";", null)}"); + } + + #endregion Initialization + + public override string ExeName + { + get + { + // the requirement is that this DLL (i.e. EcTranslators.dll) is in the same folder as the AzureOpenAiExe.exe + // console app (bkz this EncConverter could be being launched by Paratext, which could even be using a different + // version of the core SilEncConverters40.dll--in its install folder), and which wouldn't have this + // EcTranslators DLL, OR by Word, which knows nothing about either and launches them via COM). + // So to get the path where the AzureOpenAiExe is located, it should be the same location as this DLL + // (e.g. the SILConverters install dir) + var pathToDll = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + return Path.Combine(pathToDll, $"{strExeDefPath}.exe"); + } + } + + public override string Arguments + { + get + { + var azureOpenAiKey = AzureOpenAiKeyOverride; + var azureOpenAiDeploymentName = AzureOpenAiDeploymentName; + var azureOpenAiEndpoint = AzureOpenAiEndpoint; + if (!IsValidParameter(EnvVarNameKey, ref azureOpenAiKey) || + !IsValidParameter(EnvVarNameDeploymentName, ref azureOpenAiDeploymentName) || + !IsValidParameter(EnvVarNameEndPoint, ref azureOpenAiEndpoint)) + { + MessageBox.Show(String.Format("You need to edit this converter instance and enter the key to your Azure Open AI resource in the Setup tab.{0}You may need to do this for each Client app, since they store their Settings separately.{0}You can also use environment variables to set these values:{0}{1}{0}{2}{0}{3}", + Environment.NewLine, EnvVarNameKey, EnvVarNameDeploymentName, EnvVarNameEndPoint), + EncConverters.cstrCaption); + } + + // The system prompt can't have double quotes in it, bkz those are used for separating the 4 command line parameters, + // So convert them to single quotes, which should also work + return $"\"{azureOpenAiDeploymentName}\" \"{azureOpenAiEndpoint}\" \"{azureOpenAiKey}\" \"{AiSystemInstructions.Replace("\"", "'")}\""; + } + } + + private static bool IsValidParameter(string envVarName, ref string parameter) + { + return !string.IsNullOrEmpty(parameter) || + !string.IsNullOrEmpty((parameter = Environment.GetEnvironmentVariable(envVarName))); + } + + #region Misc helpers + + protected override EncodingForm DefaultUnicodeEncForm(bool bForward, bool bLHS) + { + // if it's unspecified, then we want UTF-16 + return EncodingForm.UTF16; + } + + #endregion Misc helpers + + #region Abstract Base Class Overrides + protected override string GetConfigTypeName + { + get { return typeof(AzureOpenAiEncConverterConfig).AssemblyQualifiedName; } + } + + protected override Encoding StandardOutputEncoding + { + get + { + return Encoding.Unicode; + } + } + + protected override Encoding StandardInputEncoding + { + get + { + return Encoding.Unicode; + } + } + + #endregion Abstract Base Class Overrides + } +} diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverterConfig.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverterConfig.cs new file mode 100644 index 00000000..4fe73d53 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverterConfig.cs @@ -0,0 +1,65 @@ +using System; +using System.Windows.Forms; +using ECInterfaces; // for IEncConverter + +//uncomment the following line for verbose debugging output using Console.WriteLine +//#define VERBOSE_DEBUGGING + +namespace SilEncConverters40.EcTranslators.AzureOpenAI +{ + public class AzureOpenAiEncConverterConfig : EncConverterConfig + { + public AzureOpenAiEncConverterConfig() + : base + ( + typeof(AzureOpenAiEncConverter).FullName, + AzureOpenAiEncConverter.strDisplayName, + AzureOpenAiEncConverter.strHtmlFilename, + ProcessTypeFlags.Translation + ) + { + } + + [STAThread] + public override bool Configure + ( + IEncConverters aECs, + string strFriendlyName, + ConvType eConversionType, + string strLhsEncodingID, + string strRhsEncodingID + ) + { +#if VERBOSE_DEBUGGING + Console.WriteLine("AzureOpenAiEncConverterConfig(3).Configure BEGIN"); +#endif + AzureOpenAiAutoConfigDialog form = new AzureOpenAiAutoConfigDialog(aECs, m_strDisplayName, m_strFriendlyName, + m_strConverterID, m_eConversionType, m_strLhsEncodingID, m_strRhsEncodingID, + m_lProcessType, m_bIsInRepository); + +#if VERBOSE_DEBUGGING + Console.WriteLine("AzureOpenAiEncConverterConfig.Configure END"); +#endif + return base.Configure(form); + } + + public override void DisplayTestPage + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + Console.Error.WriteLine("AzureOpenAiEncConverterConfig.DisplayTestPage() BEGIN"); + InitializeFromThis(ref strFriendlyName, ref strConverterIdentifier, + ref eConversionType, ref strTestData); + + AzureOpenAiAutoConfigDialog form = new AzureOpenAiAutoConfigDialog(aECs, strFriendlyName, + strConverterIdentifier, eConversionType, strTestData); + + base.DisplayTestPage(form); + } + } +} diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config new file mode 100644 index 00000000..7a0d89e9 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj new file mode 100644 index 00000000..f1a3052b --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj @@ -0,0 +1,120 @@ + + + + + Debug + AnyCPU + {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE} + Exe + SilEncConverters40.EcTranslators.AzureOpenAI.AzureOpenAiExe + AzureOpenAiExe + v4.8 + 512 + 8.0 + true + true + + + true + ..\..\..\..\output\x64\Debug\ + DEBUG;TRACE + full + x64 + 8.0 + prompt + true + + + ..\..\..\..\output\x64\Release\ + TRACE + true + pdbonly + x64 + 8.0 + prompt + true + + + true + ..\..\..\..\output\Win32\Debug\ + DEBUG;TRACE + full + x86 + 8.0 + prompt + true + + + ..\..\..\..\output\Win32\Release\ + TRACE + true + pdbonly + x86 + 8.0 + prompt + true + + + + ..\..\..\..\packages\Azure.AI.OpenAI.1.0.0-beta.8\lib\netstandard2.0\Azure.AI.OpenAI.dll + + + ..\..\..\..\packages\Azure.Core.1.35.0\lib\net472\Azure.Core.dll + + + ..\..\..\..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + True + + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + ..\..\..\..\packages\System.Diagnostics.DiagnosticSource.7.0.2\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + ..\..\..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + True + + + ..\..\..\..\packages\System.Memory.Data.7.0.0\lib\net462\System.Memory.Data.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\..\..\..\packages\System.Runtime.CompilerServices.Unsafe.7.0.0-preview.2.22152.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\..\..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll + True + + + ..\..\..\..\packages\System.Text.Json.7.0.3\lib\net462\System.Text.Json.dll + True + + + ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs new file mode 100644 index 00000000..4d754fd4 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs @@ -0,0 +1,175 @@ +#if DEBUG +#define LogResults +#endif + +using Azure.AI.OpenAI; +using Azure; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; + +namespace SilEncConverters40.EcTranslators.AzureOpenAI.AzureOpenAiExe +{ + internal class Program + { +#if LogResults + private const string LogFilePath = @"C:\btmp\AzureOpenAiLog.txt"; +#endif + private const string ResponsePrefix = "Free translation: "; + private const string EnvVarNameDeploymentName = "EncConverters_AzureOpenAiDeploymentName"; + private const string EnvVarNameEndPoint = "EncConverters_AzureOpenAiEndpoint"; + private const string EnvVarNameKey = "EncConverters_AzureOpenAiKey"; + + private static readonly char[] TrimmableChars = new char[] { '\r', '\n', ' ' }; + + static async Task Main(string[] args) + { + // set the stdin/out to Unicode + Console.InputEncoding = Encoding.Unicode; + Console.OutputEncoding = Encoding.Unicode; + + if (!IsValidParameters(args, out string deploymentName, out string endpoint, out string key, out string systemPrompt)) + return; + + // Pass the deployment name you chose when you created/deployed the model in Azure OpenAI Studio. + var client = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(key)); + + // create the ChatMessages w/ the given systemPrompt + var chatMessages = new List + { + new ChatMessage(ChatRole.System, systemPrompt) + }; + var chatCompletionOptions = new ChatCompletionsOptions(chatMessages); + + // in case there are multiple lines (e.g. what Paratext will do if the verse has multiple paragraphs), + // process in a while loop + var index = 0; + List input = null; // new List { "वहाँ वह विश्राम के दिन प्रार्थना घर में जाकर लोगों को परमेश्वर का वचन सुनाने लगा। सब लोग सुनकर चकित हो गये।", "", "परंतु कई तो यह भी कहने लगे, “यह ज्ञान इसको कहाँ से आया!? और ऐसे सामर्थ्‍य के काम यह कैसे करता है, जिसकी चर्चा सब लोग कर रहे हैं!?" }; + while ((input != null && input.Count > index) || (input == null && Console.In.Peek() != -1)) + { + var strInput = (input != null) + ? input[index++] + : Console.ReadLine(); + if (String.IsNullOrEmpty(strInput?.Trim(TrimmableChars))) // don't actually trim them, but just for the sake of finding nothing to translate... + continue; + + // add the string to be translated to as the 'user' message + chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.User, strInput)); + + // call the service to process the user msg based on the given system prompt + var chatCompletions = await client.GetChatCompletionsAsync(deploymentName, chatCompletionOptions); + + // clean up and return the "assistent's response" + var strOutput = HarvestResult(strInput, chatCompletions.Value.Choices[0]); + + // put that back in the chat, in case we are processing multiple lines + // (this'll make them 'related' for better translation) + chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.Assistant, strOutput)); + } + + for (var i = 1; i < chatCompletionOptions.Messages.Count;) + { + var strInput = chatCompletionOptions.Messages[i++].Content; + var strOutput = chatCompletionOptions.Messages[i++].Content; + +#if LogResults + File.AppendAllText(LogFilePath, string.Format("{1}=>{2}:{3}=>{4}{0}", Environment.NewLine, systemPrompt, i / 2, strInput, strOutput)); +#endif + // write the responses to the standard out to return it + Console.WriteLine(strOutput); + } + } + + private static bool IsValidParameters(string[] args, out string deploymentName, out string endpoint, out string key, out string systemPrompt) + { + if (args.Length != 4) + { + Console.WriteLine(String.Format("Usage:{0}{0}{1} \"\" \"\" \"\" \"\"", Environment.NewLine, typeof(Program).Namespace)); + deploymentName = endpoint = key = systemPrompt = null; + return false; + } + + deploymentName = args[0]; + endpoint = args[1]; + key = args[2]; + systemPrompt = args[3]; + + if (!IsValidParameter(EnvVarNameDeploymentName, ref deploymentName)) + { + Console.WriteLine($"The calling program failed to send the DeploymentName (first) command line parameter. You can also pass it by setting the '{EnvVarNameDeploymentName}' environment variable."); + return false; + } + + if (!IsValidParameter(EnvVarNameEndPoint, ref endpoint)) + { + Console.WriteLine($"The calling program failed to send the Azure OpenAI Resource Endpoint (second) command line parameter. You can also pass it by setting the '{EnvVarNameEndPoint}' environment variable."); + return false; + } + + if (!IsValidParameter(EnvVarNameKey, ref key)) + { + Console.WriteLine($"The calling program failed to send the Azure OpenAI Resource key (third) command line parameter. You can also pass it by setting the '{EnvVarNameKey}' environment variable."); + return false; + } + + if (String.IsNullOrEmpty(systemPrompt)) + { + Console.WriteLine("The calling program failed to send the System Prompt (forth) command line parameter"); + return false; + } + + return true; + } + + private static bool IsValidParameter(string envVarName, ref string parameter) + { + return !string.IsNullOrEmpty(parameter) || + !string.IsNullOrEmpty((parameter = Environment.GetEnvironmentVariable(envVarName))); + } + + private static string HarvestResult(string strInput, ChatChoice chatChoice) + { + var content = chatChoice.Message.Content; + + // if the content is empty... + if (string.IsNullOrEmpty(content)) + { + // most likely a content filter happened + var contentFilterReason = String.Empty; + if (chatChoice.ContentFilterResults.Violence.Filtered) + contentFilterReason = "Violence"; + if (chatChoice.ContentFilterResults.Hate.Filtered) + contentFilterReason = "Hate"; + if (chatChoice.ContentFilterResults.SelfHarm.Filtered) + contentFilterReason = "SelfHarm"; + if (chatChoice.ContentFilterResults.Sexual.Filtered) + contentFilterReason = "Sexual"; + + if (!String.IsNullOrEmpty(contentFilterReason)) + content = $""; + else + content = ""; + } + return CleanString(strInput, content); + } + + private static string CleanString(string input, string output) + { + if (!String.IsNullOrEmpty(input) && input.Length > 1) + { + if (input.First() != '"') + output = output.TrimStart('"'); + if (input.Length > 2 && input.Last() != '"') + output = output.TrimEnd('"'); + } + + if (output.StartsWith(ResponsePrefix)) + output = output.Substring(ResponsePrefix.Length); + + return output; + } + } +} diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Properties/AssemblyInfo.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..15744ecf --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("AzureOpenAi")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("AzureOpenAi")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4f6ff8ad-6beb-4104-b123-7fa9c2dc0bbe")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config new file mode 100644 index 00000000..41e54c84 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.Designer.cs b/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.Designer.cs new file mode 100644 index 00000000..e83bf752 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.Designer.cs @@ -0,0 +1,196 @@ + +namespace SilEncConverters40.EcTranslators.AzureOpenAI +{ + partial class QueryForAzureKeyDeploymentNameAndEndpoint + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.labelAzureOpenAiKey = new System.Windows.Forms.Label(); + this.labelAzureOpenAiEndpoint = new System.Windows.Forms.Label(); + this.linkLabelInstructions = new System.Windows.Forms.LinkLabel(); + this.labelAzureOpeAiDeploymentName = new System.Windows.Forms.Label(); + this.textBoxAzureOpenAiKey = new System.Windows.Forms.TextBox(); + this.textBoxAzureOpenAiDeploymentName = new System.Windows.Forms.TextBox(); + this.textBoxAzureOpenAiEndpoint = new System.Windows.Forms.TextBox(); + this.buttonOK = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel1.ColumnCount = 4; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.buttonCancel, 2, 4); + this.tableLayoutPanel1.Controls.Add(this.labelAzureOpenAiKey, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.labelAzureOpenAiEndpoint, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.linkLabelInstructions, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.labelAzureOpeAiDeploymentName, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.textBoxAzureOpenAiKey, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxAzureOpenAiDeploymentName, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.textBoxAzureOpenAiEndpoint, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.buttonOK, 1, 4); + this.tableLayoutPanel1.Location = new System.Drawing.Point(12, 12); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(577, 223); + this.tableLayoutPanel1.TabIndex = 0; + // + // buttonCancel + // + this.buttonCancel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(241, 197); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 7; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = true; + // + // labelAzureOpenAiKey + // + this.labelAzureOpenAiKey.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelAzureOpenAiKey.AutoSize = true; + this.labelAzureOpenAiKey.Location = new System.Drawing.Point(26, 18); + this.labelAzureOpenAiKey.Name = "labelAzureOpenAiKey"; + this.labelAzureOpenAiKey.Size = new System.Drawing.Size(128, 13); + this.labelAzureOpenAiKey.TabIndex = 1; + this.labelAzureOpenAiKey.Text = "Enter Azure Open AI Key:"; + // + // labelAzureOpenAiEndpoint + // + this.labelAzureOpenAiEndpoint.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelAzureOpenAiEndpoint.AutoSize = true; + this.labelAzureOpenAiEndpoint.Location = new System.Drawing.Point(3, 118); + this.labelAzureOpenAiEndpoint.Name = "labelAzureOpenAiEndpoint"; + this.labelAzureOpenAiEndpoint.Size = new System.Drawing.Size(151, 13); + this.labelAzureOpenAiEndpoint.TabIndex = 3; + this.labelAzureOpenAiEndpoint.Text = "Enter Language API Endpoint:"; + // + // linkLabelInstructions + // + this.linkLabelInstructions.AutoSize = true; + this.tableLayoutPanel1.SetColumnSpan(this.linkLabelInstructions, 4); + this.linkLabelInstructions.Location = new System.Drawing.Point(3, 150); + this.linkLabelInstructions.Name = "linkLabelInstructions"; + this.linkLabelInstructions.Size = new System.Drawing.Size(335, 13); + this.linkLabelInstructions.TabIndex = 5; + this.linkLabelInstructions.TabStop = true; + this.linkLabelInstructions.Text = "see {0} for instructions on creating your own Azure Open AI Resource"; + this.linkLabelInstructions.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelInstructions_LinkClicked); + // + // labelAzureOpeAiDeploymentName + // + this.labelAzureOpeAiDeploymentName.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelAzureOpeAiDeploymentName.AutoSize = true; + this.labelAzureOpeAiDeploymentName.Location = new System.Drawing.Point(29, 68); + this.labelAzureOpeAiDeploymentName.Name = "labelAzureOpeAiDeploymentName"; + this.labelAzureOpeAiDeploymentName.Size = new System.Drawing.Size(125, 13); + this.labelAzureOpeAiDeploymentName.TabIndex = 1; + this.labelAzureOpeAiDeploymentName.Text = "Enter Deployment Name:"; + // + // textBoxAzureOpenAiKey + // + this.textBoxAzureOpenAiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel1.SetColumnSpan(this.textBoxAzureOpenAiKey, 3); + this.textBoxAzureOpenAiKey.Location = new System.Drawing.Point(160, 15); + this.textBoxAzureOpenAiKey.Name = "textBoxAzureOpenAiKey"; + this.textBoxAzureOpenAiKey.Size = new System.Drawing.Size(414, 20); + this.textBoxAzureOpenAiKey.TabIndex = 2; + // + // textBoxAzureOpenAiDeploymentName + // + this.textBoxAzureOpenAiDeploymentName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel1.SetColumnSpan(this.textBoxAzureOpenAiDeploymentName, 3); + this.textBoxAzureOpenAiDeploymentName.Location = new System.Drawing.Point(160, 65); + this.textBoxAzureOpenAiDeploymentName.Name = "textBoxAzureOpenAiDeploymentName"; + this.textBoxAzureOpenAiDeploymentName.Size = new System.Drawing.Size(414, 20); + this.textBoxAzureOpenAiDeploymentName.TabIndex = 2; + // + // textBoxAzureOpenAiEndpoint + // + this.textBoxAzureOpenAiEndpoint.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel1.SetColumnSpan(this.textBoxAzureOpenAiEndpoint, 3); + this.textBoxAzureOpenAiEndpoint.Location = new System.Drawing.Point(160, 115); + this.textBoxAzureOpenAiEndpoint.Name = "textBoxAzureOpenAiEndpoint"; + this.textBoxAzureOpenAiEndpoint.Size = new System.Drawing.Size(414, 20); + this.textBoxAzureOpenAiEndpoint.TabIndex = 4; + // + // buttonOK + // + this.buttonOK.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.buttonOK.Location = new System.Drawing.Point(160, 197); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.Size = new System.Drawing.Size(75, 23); + this.buttonOK.TabIndex = 6; + this.buttonOK.Text = "&OK"; + this.buttonOK.UseVisualStyleBackColor = true; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // QueryForAzureKeyDeploymentNameAndEndpoint + // + this.AcceptButton = this.buttonOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(601, 247); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "QueryForAzureKeyDeploymentNameAndEndpoint"; + this.Text = "Enter Azure Open AI Resource Key, Deployment Name, and Endpoint"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Label labelAzureOpenAiKey; + private System.Windows.Forms.Label labelAzureOpenAiEndpoint; + private System.Windows.Forms.TextBox textBoxAzureOpenAiKey; + private System.Windows.Forms.TextBox textBoxAzureOpenAiEndpoint; + private System.Windows.Forms.LinkLabel linkLabelInstructions; + private System.Windows.Forms.Label labelAzureOpeAiDeploymentName; + private System.Windows.Forms.TextBox textBoxAzureOpenAiDeploymentName; + } +} \ No newline at end of file diff --git a/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.cs b/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.cs new file mode 100644 index 00000000..0af250aa --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.cs @@ -0,0 +1,58 @@ +using System.Diagnostics; +using System.Windows.Forms; + +namespace SilEncConverters40.EcTranslators.AzureOpenAI +{ + public partial class QueryForAzureKeyDeploymentNameAndEndpoint : Form + { + private const string InstructionsFormat = "see {0} for instructions on creating your own Azure Open AI Resource"; + public QueryForAzureKeyDeploymentNameAndEndpoint(string azureOpenAiKey, string azureOpenAiDeploymentName, string azureOpenAiEndpoint) + { + InitializeComponent(); + + textBoxAzureOpenAiKey.Text = azureOpenAiKey; + textBoxAzureOpenAiDeploymentName.Text = azureOpenAiDeploymentName; + textBoxAzureOpenAiEndpoint.Text = azureOpenAiEndpoint; + var azureOpenAiKeyLocationDialogInstructionUrl = Properties.Settings.Default.AzureOpenAiKeyLocationDialogInstructionUrl; + var azureOpenAiKeyLocationDialogInstruction = string.Format(InstructionsFormat, azureOpenAiKeyLocationDialogInstructionUrl); + linkLabelInstructions.Text = azureOpenAiKeyLocationDialogInstruction; + linkLabelInstructions.Links.Add(4, azureOpenAiKeyLocationDialogInstructionUrl.Length, + azureOpenAiKeyLocationDialogInstructionUrl); + } + + public string AzureOpenAiKeyOverride + { + get + { + return textBoxAzureOpenAiKey.Text; + } + } + + public string AzureOpenAiDeploymentName + { + get + { + return textBoxAzureOpenAiDeploymentName.Text; + } + } + + public string AzureOpenAiEndpoint + { + get + { + return textBoxAzureOpenAiEndpoint.Text; + } + } + + private void linkLabelInstructions_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + Process.Start("https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource"); + } + + private void buttonOK_Click(object sender, System.EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + } +} diff --git a/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.resx b/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/QueryForAzureKeyDeploymentNameAndEndpoint.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/EcTranslators/EcTranslators.csproj b/src/EcTranslators/EcTranslators.csproj index 99577e80..a4737d71 100644 --- a/src/EcTranslators/EcTranslators.csproj +++ b/src/EcTranslators/EcTranslators.csproj @@ -76,6 +76,20 @@
+ + + + Form + + + AzureOpenAiAutoConfigDialog.cs + + + Form + + + QueryForAzureKeyDeploymentNameAndEndpoint.cs + Form @@ -163,6 +177,12 @@ + + AzureOpenAiAutoConfigDialog.cs + + + QueryForAzureKeyDeploymentNameAndEndpoint.cs + QueryForAzureKeyAndLocation.cs @@ -210,7 +230,7 @@ 7.0.4 - 7.0.10 + 7.0.13 13.0.3 diff --git a/src/EcTranslators/Properties/Resources.Designer.cs b/src/EcTranslators/Properties/Resources.Designer.cs index 36fede68..a4461dd5 100644 --- a/src/EcTranslators/Properties/Resources.Designer.cs +++ b/src/EcTranslators/Properties/Resources.Designer.cs @@ -78,6 +78,51 @@ internal static string GoogleTranslatorKeyDialogInstructionUrl { } } + /// + /// Looks up a localized string similar to Click this button to enter your own Resource key and other information needed to use the Microsoft Azure Open AI Service. See https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource, for more information on how to get your own Azure Open AI Resource. Note: there is no default Resource for this converter; you must get your own to use it.. + /// + internal static string HelpForAzureOpenAiAddYourOwnApiKey { + get { + return ResourceManager.GetString("HelpForAzureOpenAiAddYourOwnApiKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the name of the language you want the Azure Open AI Resource to tranlate from (e.g. Hindi). + /// + internal static string HelpForAzureOpenAiSourceLanguageTextBox { + get { + return ResourceManager.GetString("HelpForAzureOpenAiSourceLanguageTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can add one of the existing additions to the base system prompt using the values in this drop down box (or type in your own). + /// + internal static string HelpForAzureOpenAiSystemPromptAdditionsComboBox { + get { + return ResourceManager.GetString("HelpForAzureOpenAiSystemPromptAdditionsComboBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This box shows the System Prompt that will be sent to the Azure Open AI Resource. + /// + internal static string HelpForAzureOpenAiSystemPromptTextBox { + get { + return ResourceManager.GetString("HelpForAzureOpenAiSystemPromptTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the name of the language you want the Azure Open AI Resource to tranlate into (e.g. English). + /// + internal static string HelpForAzureOpenAiTargetLanguageTextBox { + get { + return ResourceManager.GetString("HelpForAzureOpenAiTargetLanguageTextBox", resourceCulture); + } + } + /// /// Looks up a localized string similar to Click this button to enter your own API key from Microsoft Azure. See the "Prerequisites" section on the page, https://docs.microsoft.com/en-us/azure/cognitive-services/translator/quickstart-translator, for how to get your own key (e.g. if the default API key has run out of translation support -- note: the default API key is using the free pricing tier and is limited to 2 million characters/month). /// diff --git a/src/EcTranslators/Properties/Resources.resx b/src/EcTranslators/Properties/Resources.resx index fb873263..1f4c9389 100644 --- a/src/EcTranslators/Properties/Resources.resx +++ b/src/EcTranslators/Properties/Resources.resx @@ -123,6 +123,21 @@ https://cloud.google.com/translate/docs/setup#creating_service_accounts_and_keys + + Click this button to enter your own Resource key and other information needed to use the Microsoft Azure Open AI Service. See https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource, for more information on how to get your own Azure Open AI Resource. Note: there is no default Resource for this converter; you must get your own to use it. + + + Enter the name of the language you want the Azure Open AI Resource to tranlate from (e.g. Hindi) + + + You can add one of the existing additions to the base system prompt using the values in this drop down box (or type in your own) + + + This box shows the System Prompt that will be sent to the Azure Open AI Resource + + + Enter the name of the language you want the Azure Open AI Resource to tranlate into (e.g. English) + Click this button to enter your own API key from Microsoft Azure. See the "Prerequisites" section on the page, https://docs.microsoft.com/en-us/azure/cognitive-services/translator/quickstart-translator, for how to get your own key (e.g. if the default API key has run out of translation support -- note: the default API key is using the free pricing tier and is limited to 2 million characters/month) diff --git a/src/EcTranslators/Properties/Settings.Designer.cs b/src/EcTranslators/Properties/Settings.Designer.cs index 80b1ac78..9c411628 100644 --- a/src/EcTranslators/Properties/Settings.Designer.cs +++ b/src/EcTranslators/Properties/Settings.Designer.cs @@ -181,5 +181,74 @@ public string GoogleCloudBillingProjectName { this["GoogleCloudBillingProjectName"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string AzureOpenAiEndpoint { + get { + return ((string)(this["AzureOpenAiEndpoint"])); + } + set { + this["AzureOpenAiEndpoint"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string AzureOpenAiDeploymentName { + get { + return ((string)(this["AzureOpenAiDeploymentName"])); + } + set { + this["AzureOpenAiDeploymentName"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string AzureOpenAiKeyOverride { + get { + return ((string)(this["AzureOpenAiKeyOverride"])); + } + set { + this["AzureOpenAiKeyOverride"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource" + + "")] + public string AzureOpenAiKeyLocationDialogInstructionUrl { + get { + return ((string)(this["AzureOpenAiKeyLocationDialogInstructionUrl"])); + } + set { + this["AzureOpenAiKeyLocationDialogInstructionUrl"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute(@" + + with a 'free translation' style + with a 'literal translation' style + with a 'free translation' style aimed at high school students + in the Devanagari script + using 'Yoda speak' + UseSystemPrompt: Translate from Hindi into English. +")] + public global::System.Collections.Specialized.StringCollection AzureOpenAiSystemPromptAdditions { + get { + return ((global::System.Collections.Specialized.StringCollection)(this["AzureOpenAiSystemPromptAdditions"])); + } + set { + this["AzureOpenAiSystemPromptAdditions"] = value; + } + } } } diff --git a/src/EcTranslators/Properties/Settings.settings b/src/EcTranslators/Properties/Settings.settings index 6e89a01e..7748d0f5 100644 --- a/src/EcTranslators/Properties/Settings.settings +++ b/src/EcTranslators/Properties/Settings.settings @@ -32,5 +32,28 @@ projects/bright-coyote-381812 + + + + + + + + + + + https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource + + + <?xml version="1.0" encoding="utf-16"?> +<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <string>with a 'free translation' style</string> + <string>with a 'literal translation' style</string> + <string>with a 'free translation' style aimed at high school students</string> + <string>in the Devanagari script</string> + <string>using 'Yoda speak'</string> + <string>UseSystemPrompt: Translate from Hindi into English.</string> +</ArrayOfString> + \ No newline at end of file diff --git a/src/EcTranslators/app.config b/src/EcTranslators/app.config index e8c13986..8472476d 100644 --- a/src/EcTranslators/app.config +++ b/src/EcTranslators/app.config @@ -22,17 +22,25 @@ + + + + + + + + - + @@ -48,19 +56,19 @@ - + - + - + - + @@ -105,6 +113,30 @@ projects/bright-coyote-381812 + + + + + + + + + + + https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource + + + + + with a 'free translation' style + with a 'literal translation' style + with a 'free translation' style aimed at high school students + in the Devanagari script + using 'Yoda speak' + UseSystemPrompt: Translate from Hindi into English. + + + \ No newline at end of file diff --git a/src/EncCnvtrs/EncConverters.cs b/src/EncCnvtrs/EncConverters.cs index f48b80e6..40fa2003 100755 --- a/src/EncCnvtrs/EncConverters.cs +++ b/src/EncCnvtrs/EncConverters.cs @@ -81,10 +81,11 @@ public class EncConverters : Hashtable, IEncConverters public const string strTypeSILfallback = "SIL.fallback"; public const string strTypeSILadaptit = "SIL.AdaptItKB"; public const string strTypeSILadaptitGuesser = "SIL.AdaptItKBGuesser"; - public const string strTypeSILtechHindiSite = "SIL.TechHindiWebPage"; - public const string strTypeSILBingTranslator = "SIL.BingTranslator"; + public const string strTypeSILtechHindiSite = "SIL.TechHindiWebPage"; + public const string strTypeSILBingTranslator = "SIL.BingTranslator"; public const string strTypeSILGoogleTranslator = "SIL.GoogleTranslator"; - public const string strTypeSILDeepLTranslator = "SIL.DeepLTranslator"; + public const string strTypeSILDeepLTranslator = "SIL.DeepLTranslator"; + public const string strTypeSILAzureOpenAiTranslator = "SIL.AzureOpenAI"; public const string cstrTempConverterPrefix = "Temporary Converter"; @@ -626,7 +627,7 @@ protected void GetConversionEnginesSupported() // then the converters are keyed either based on the process type or the // extension (these are used by the "Add" method where the user doesn't // have to specify the implementation type) - if (!aDetailsRow.IsDefiningProcessTypeNull() && (aDetailsRow.DefiningProcessType != 0)) // but not for "Don't know" + if (!aDetailsRow.IsDefiningProcessTypeNull() && (aDetailsRow.DefiningProcessType != 0)) // but not for "Don't know" { int nProcessType = aDetailsRow.DefiningProcessType; @@ -2428,7 +2429,7 @@ public IEncConverter InstantiateIEncConverter(string strProgID, string strAssemb catch (Exception ex) { // see if we can load the assembly from an installation of SILConverters - // strAssemblySpec = e.g. "SilEncConverters40, Version=4.0.0.0, Culture=neutral, PublicKeyToken=f1447bae1e63f485" + // strAssemblySpec = e.g. "SilEncConverters40, Version=4.0.0.0, Culture=neutral, PublicKeyToken=f1447bae1e63f485" var index = strAssemblySpec.IndexOf(','); if (index > 0) { diff --git a/src/EncCnvtrs/ExeEncConverter.cs b/src/EncCnvtrs/ExeEncConverter.cs index 1a03c437..2f7e3bf8 100755 --- a/src/EncCnvtrs/ExeEncConverter.cs +++ b/src/EncCnvtrs/ExeEncConverter.cs @@ -7,6 +7,7 @@ using System.Diagnostics; // for ProcessStartInfo using System.Text; // for ASCIIEncoding using ECInterfaces; // for IEncConverter +using System.Linq; namespace SilEncConverters40 { @@ -144,7 +145,7 @@ protected virtual ProcessStartInfo ProcessStarter { var progpath = Path.Combine(WorkingDir, ExeName); if (!File.Exists(progpath)) - progpath = ExeName; // assume program is in the user's path. + progpath = ExeName; // assume program is in the user's path. m_psi = new ProcessStartInfo(progpath) { @@ -183,6 +184,9 @@ protected virtual Encoding StandardInputEncoding #region Implementation protected string DoExeCall(string sInput) { + if (String.IsNullOrEmpty(sInput)) + return sInput; + var si = ProcessStarter; string strOutput; @@ -203,6 +207,7 @@ protected string DoExeCall(string sInput) // call a virtual to do this in case the sub-classes have special behavior strOutput = ReadFromExeOutputStream(sr, p.StandardError); + strOutput = CleanOutput(sInput, strOutput); } catch (Exception e) { @@ -213,6 +218,36 @@ protected string DoExeCall(string sInput) return strOutput; } + + private char[] charsToTrim = { '\n', '\r' }; + + /// + /// remove any final \n\r that might be added if the input doesn't have it (it seems that some standard outputs add it by default + /// + /// + /// + /// + /// + private string CleanOutput(string sInput, string strOutput) + { + return (!string.IsNullOrEmpty(sInput) && sInput.Length > 1 && !charsToTrim.Contains(sInput.Last()) && + !string.IsNullOrEmpty(strOutput) && strOutput.Length > 1 && charsToTrim.Contains(strOutput.Last())) + ? strOutput.TrimEnd(charsToTrim) + : strOutput; + } + + private static unsafe bool ContainsCrLfs(byte* lpInBuffer, int nInLen) + { + var bContainsCrLfs = false; + for (int i = 0; (i < nInLen) && !bContainsCrLfs; i++) + { + if ((lpInBuffer[i] == '\r') && (lpInBuffer[i + 1] == '\n')) + bContainsCrLfs = true; + } + + return bContainsCrLfs; + } + #endregion Implementation #region Abstract Base Class Overrides @@ -227,6 +262,15 @@ ref int rnOutLen { rnOutLen = 0; + // 2022-11-29 BE: it seems that some programs (e.g. Azure Open AI) eats '\r's... if the input + // has any '\r\n' sequences and the output has just '\n's, then insert the '\r's back in + // I was thinking we probably don't want to do this on Linux (if so, add "&& !Util.IsUnix") + // but if Linux doesn't use CRs, then this function will return false anyway (and if it does + // then Azure Open AI will probably (wrongly) strip them out and we (probably) want them put + // back in. Worst case, add a parameter to the converter Specification to indicate whether + // you want this to be done or not. + var bContainsCrLfs = ContainsCrLfs(lpInBuffer, nInLen); + // we need to put it *back* into a string because the StreamWriter that will // ultimately write to the StandardInput uses a string. For now, the only user // is Perl, which only supports Unicode to Unicode and so the data coming in @@ -260,6 +304,19 @@ ref int rnOutLen // put it in the output buffer rnOutLen = strOutput.Length * 2; rnOutLen = ECNormalizeData.StringToByteStar(strOutput, lpOutBuffer, rnOutLen, false); + + if (bContainsCrLfs && !ContainsCrLfs(lpOutBuffer, rnOutLen)) + { + // need to put the '\r's back in + for (int i = 0; i < rnOutLen; i++) + { + if ((lpOutBuffer[i] == '\n') && ((i == 0) || (lpOutBuffer[i - 1] != '\r'))) + { + ECNormalizeData.MemMove(lpOutBuffer + i + 1, lpOutBuffer + i, rnOutLen++ - i); + lpOutBuffer[i] = (byte)'\r'; + } + } + } } #endregion Abstract Base Class Overrides } diff --git a/src/EncCnvtrs/WebBrowserGecko.cs b/src/EncCnvtrs/WebBrowserGecko.cs index b3242206..da9b11ff 100644 --- a/src/EncCnvtrs/WebBrowserGecko.cs +++ b/src/EncCnvtrs/WebBrowserGecko.cs @@ -95,12 +95,11 @@ public async override Task ExecuteScriptFunctionAsync(string functionNam public override Task NavigateAsync(string filePath) { - if (!File.Exists(filePath)) + if (!filePath.StartsWith("http") && !File.Exists(filePath)) { const string cstrFileNameToEditSaveAsHtml = "CantReadMhtFiles.htm"; filePath = Path.Combine(Path.GetDirectoryName(filePath), cstrFileNameToEditSaveAsHtml); - System.Diagnostics.Debug.Assert(File.Exists(filePath)); } // GeckoWebBrowser.Navigate("file://" + filePath); diff --git a/src/RunTests/app.config b/src/RunTests/app.config index 3b2a88d1..3ae3cc65 100644 --- a/src/RunTests/app.config +++ b/src/RunTests/app.config @@ -31,7 +31,7 @@ - + @@ -41,10 +41,18 @@ + + + + + + + + @@ -55,19 +63,19 @@ - + - + - + - + diff --git a/src/TestEncCnvtrs/TestEcTranslators.cs b/src/TestEncCnvtrs/TestEcTranslators.cs index d33f798c..b7e85ba3 100644 --- a/src/TestEncCnvtrs/TestEcTranslators.cs +++ b/src/TestEncCnvtrs/TestEcTranslators.cs @@ -12,326 +12,354 @@ using SilEncConverters40.EcTranslators.BingTranslator; using SilEncConverters40.EcTranslators.DeepLTranslator; using SilEncConverters40.EcTranslators.GoogleTranslator; +using SilEncConverters40.EcTranslators.AzureOpenAI; using System.Threading.Tasks; namespace TestEncCnvtrs { - [TestFixture] - public class TestEcTranslators - { - EncConverters m_encConverters; - bool m_fWroteRepoFile; - bool m_fSetRegistryValue; - string m_repoFile; - - /// -------------------------------------------------------------------- - /// - /// Global initialization, called once before any test in this class - /// ("fixture") is run. - /// - /// -------------------------------------------------------------------- - [OneTimeSetUp] - public void InitForClass() - { - Util.DebugWriteLine(this, "BEGIN"); - if (Util.IsUnix) - { - // Make sure we get set up to be able to access Registry.LocalMachine. - string machine_store = Environment.GetEnvironmentVariable("MONO_REGISTRY_PATH"); - if (machine_store == null) - { - Console.WriteLine("First, make sure that " + Util.CommonAppDataPath() + - " exists and is writeable by everyone."); - Console.WriteLine("eg, sudo mkdir -p " + Util.CommonAppDataPath() + - " && sudo chmod +wt " + Util.CommonAppDataPath()); - Console.WriteLine("Then add the following line to ~/.profile, logout, and login again."); - Console.WriteLine("MONO_REGISTRY_PATH=" + Util.CommonAppDataPath() + - "/registry; export MONO_REGISTRY_PATH"); - // doesn't work on Maverick, but try it anyway... - Environment.SetEnvironmentVariable("MONO_REGISTRY_PATH", Util.CommonAppDataPath() + "/registry"); - } - } - - m_repoFile = null; - RegistryKey key = Registry.CurrentUser.OpenSubKey(EncConverters.HKLM_PATH_TO_XML_FILE, true); - if (key != null) - m_repoFile = key.GetValue(EncConverters.strRegKeyForStorePath) as string; - else - key = Registry.CurrentUser.CreateSubKey(EncConverters.HKLM_PATH_TO_XML_FILE); - if (String.IsNullOrEmpty(m_repoFile) && key != null) - { - m_repoFile = EncConverters.DefaultRepositoryPath; - key.SetValue(EncConverters.strRegKeyForStorePath, m_repoFile); - key.Flush(); - m_fSetRegistryValue = true; - } - if (key != null) - { - key.Close(); - key = null; - } - if (!String.IsNullOrEmpty(m_repoFile) && - File.Exists(m_repoFile) && - !File.Exists(m_repoFile + "-RESTOREME")) - { - File.Move(m_repoFile, m_repoFile + "-RESTOREME"); - } - if (!File.Exists(m_repoFile)) - m_fWroteRepoFile = true; - try - { - m_encConverters = new EncConverters(); - } - catch (Exception e) - { - Util.DebugWriteLine(this, e.Message); - } - Util.DebugWriteLine(this, "END"); - } - - /// -------------------------------------------------------------------- - /// - /// Initialization called before each test in this class ("fixture") is - /// run. - /// - /// -------------------------------------------------------------------- - [SetUp] - public void InitBeforeTest() - { - if (m_encConverters != null) - { - RemoveAnyAddedConverters(); - m_encConverters.Reinitialize(); - } - } - - /// -------------------------------------------------------------------- - /// - /// Cleanup called after each test in this class ("fixture") is run. - /// - /// -------------------------------------------------------------------- - [TearDown] - public void CleanupAfterTest() - { - if (m_encConverters != null) - { - RemoveAnyAddedConverters(); - } - } - - /// - /// Remove any added converters that are left behind due to a test - /// failure or other crash. - /// - private void RemoveAnyAddedConverters() - { - if (m_encConverters.ContainsKey("UnitTesting-ISO-8859-1")) - m_encConverters.Remove("UnitTesting-ISO-8859-1"); - if (m_encConverters.ContainsKey("UnitTesting-To-ISO-8859-1")) - m_encConverters.Remove("UnitTesting-To-ISO-8859-1"); - if (m_encConverters.ContainsKey("UnitTesting-Latin-Hebrew")) - m_encConverters.Remove ("UnitTesting-Latin-Hebrew"); - if (m_encConverters.ContainsKey("UnitTesting-Hebrew-Latin")) - m_encConverters.Remove ("UnitTesting-Hebrew-Latin"); - if (m_encConverters.ContainsKey("UnitTesting-Consonants->C")) - m_encConverters.Remove("UnitTesting-Consonants->C"); - if (m_encConverters.ContainsKey("UnitTesting-Vowels->V")) - m_encConverters.Remove("UnitTesting-Vowels->V"); - if (m_encConverters.ContainsKey("UnitTesting-Senufo-To-Unicode")) - m_encConverters.Remove("UnitTesting-Senufo-To-Unicode"); - if (m_encConverters.ContainsKey("UnitTesting-Unicode-To-Senufo")) - m_encConverters.Remove("UnitTesting-Unicode-To-Senufo"); - if (m_encConverters.ContainsKey("UnitTesting-Ann-To-Unicode")) - m_encConverters.Remove("UnitTesting-Ann-To-Unicode"); - if (m_encConverters.ContainsKey("UnitTesting-Unicode-To-Ann")) - m_encConverters.Remove("UnitTesting-Unicode-To-Ann"); - if (m_encConverters.ContainsKey("UnitTesting-ReverseString")) - m_encConverters.Remove("UnitTesting-ReverseString"); - - if (m_encConverters.ContainsKey("UnitTesting-From-CP_1252")) - m_encConverters.Remove("UnitTesting-From-CP_1252"); - if (m_encConverters.ContainsKey("UnitTesting-To-CP_1252")) - m_encConverters.Remove("UnitTesting-To-CP_1252"); - - if (m_encConverters.ContainsKey("UnitTesting-ThaiWordBreaker")) - m_encConverters.Remove("UnitTesting-ThaiWordBreaker"); - if (m_encConverters.ContainsKey("UnitTesting-AiKbConverter")) - m_encConverters.Remove("UnitTesting-AiKbConverter"); - - if (m_encConverters.ContainsKey(TestEncConverters.TechHindiSiteConverterFriendlyName)) - m_encConverters.Remove(TestEncConverters.TechHindiSiteConverterFriendlyName); - } - - /// -------------------------------------------------------------------- - /// - /// Global cleanup, called once after all tests in this class - /// ("fixture") have been run. - /// - /// -------------------------------------------------------------------- - [OneTimeTearDown] - public void CleanupForClass() - { - m_encConverters = null; - if (m_fWroteRepoFile) - { - File.Delete(m_repoFile); - m_fWroteRepoFile = false; - } - if (!String.IsNullOrEmpty(m_repoFile) && - File.Exists(m_repoFile + "-RESTOREME")) - { - if (File.Exists(m_repoFile)) - { - File.Delete(m_repoFile); // to overwrite file - } - File.Move(m_repoFile + "-RESTOREME", m_repoFile); - } - if (m_fSetRegistryValue) - { - RegistryKey key = Registry.CurrentUser.OpenSubKey(EncConverters.HKLM_PATH_TO_XML_FILE, true); - key.DeleteValue(EncConverters.strRegKeyForStorePath); - key.Flush(); - key.Close(); - m_fSetRegistryValue = false; - } - m_repoFile = null; - } - - private const string BingTranslatorConverterFriendlyName = "BingTranslator"; - - // these tests may fail if the Bing Translator resource no longer has any remaining juice... OR (more likely) - // if they change the translation - [Test] - [TestCase(ProcessTypeFlags.Translation, "Translate;hi;en", "", "")] - [TestCase(ProcessTypeFlags.Translation, "Translate;hi;en", "यीशु ने यह भी कहा,", "Jesus also said,")] - [TestCase(ProcessTypeFlags.Translation, "Translate;;en", "यीशु ने यह भी कहा,", "Jesus also said,")] - [TestCase(ProcessTypeFlags.Translation, "Translate;en;zh-Hans", "This Israel Field Guide has been developed to help you get to know the beautiful country of Israel and also to encourage you to learn and experience the incredible Word of God and the truth of the events and doctrines that it presents.", "本以色列实地指南旨在帮助您了解美丽的以色列国家,并鼓励您学习和体验上帝令人难以置信的话语以及它所呈现的事件和教义的真相。")] - [TestCase(ProcessTypeFlags.Translation | ProcessTypeFlags.Transliteration, "TranslateWithTransliterate;en;ar;;Latn", "God", "alleh")] - [TestCase(ProcessTypeFlags.Translation | ProcessTypeFlags.Transliteration, "TranslateWithTransliterate;;ar;;Latn", "God", "alleh")] - // [TestCase("TranslateWithTransliterate;;en;;Deva", "नहीं", "not")] // can't transliterate from an language=en result - // [TestCase("TranslateWithTransliterate;en;ar;;Arab", "God", "الله")] // you *can* do this, but there is no transliteration part of it (since the result is already in Arab script) - [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;hi;;Deva;Latn", "संसार", "sansar")] - [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;hi;;Latn;Deva", "sansar", "संसार")] - [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;ar;;Arab;Latn", "الله", "alleh")] - [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;ar;;Latn;Arab", "alleh", "الله")] - // [TestCase("Transliterate;ar;;;Latn", "الله", "alleh")] // this doesn't work, because with Transliterate, you must specify the fromScript - [TestCase(ProcessTypeFlags.Translation, "DictionaryLookup;en;hi", "with", "साथ")] - [TestCase(ProcessTypeFlags.Translation, "DictionaryLookup;hi;en", "से", "%2%from%than%")] // when multiple results, return the ample disambiguation syntax (cf. AdaptIt lookup converter) - [TestCase(ProcessTypeFlags.Translation, "DictionaryLookup;en;hi", "schmaboogle", "")] // when there are no translations, it returns empty string - public void TestBingTransliteratorConverter(ProcessTypeFlags processType, string converterSpec, string testInput, string testOutput) - { - m_encConverters.AddConversionMap(BingTranslatorConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, - EncConverters.strTypeSILBingTranslator, "UNICODE", "UNICODE", - processType); - - var theEc = m_encConverters[BingTranslatorConverterFriendlyName]; - - // do a forward conversion - var strOutput = theEc.Convert(testInput); - Assert.AreEqual(testOutput, strOutput); - } - - [Test] - public void TestBingTranslatorGetCapabilities() + [TestFixture] + public class TestEcTranslators + { + EncConverters m_encConverters; + bool m_fWroteRepoFile; + bool m_fSetRegistryValue; + string m_repoFile; + + /// -------------------------------------------------------------------- + /// + /// Global initialization, called once before any test in this class + /// ("fixture") is run. + /// + /// -------------------------------------------------------------------- + [OneTimeSetUp] + public void InitForClass() + { + Util.DebugWriteLine(this, "BEGIN"); + if (Util.IsUnix) + { + // Make sure we get set up to be able to access Registry.LocalMachine. + string machine_store = Environment.GetEnvironmentVariable("MONO_REGISTRY_PATH"); + if (machine_store == null) + { + Console.WriteLine("First, make sure that " + Util.CommonAppDataPath() + + " exists and is writeable by everyone."); + Console.WriteLine("eg, sudo mkdir -p " + Util.CommonAppDataPath() + + " && sudo chmod +wt " + Util.CommonAppDataPath()); + Console.WriteLine("Then add the following line to ~/.profile, logout, and login again."); + Console.WriteLine("MONO_REGISTRY_PATH=" + Util.CommonAppDataPath() + + "/registry; export MONO_REGISTRY_PATH"); + // doesn't work on Maverick, but try it anyway... + Environment.SetEnvironmentVariable("MONO_REGISTRY_PATH", Util.CommonAppDataPath() + "/registry"); + } + } + + m_repoFile = null; + RegistryKey key = Registry.CurrentUser.OpenSubKey(EncConverters.HKLM_PATH_TO_XML_FILE, true); + if (key != null) + m_repoFile = key.GetValue(EncConverters.strRegKeyForStorePath) as string; + else + key = Registry.CurrentUser.CreateSubKey(EncConverters.HKLM_PATH_TO_XML_FILE); + if (String.IsNullOrEmpty(m_repoFile) && key != null) + { + m_repoFile = EncConverters.DefaultRepositoryPath; + key.SetValue(EncConverters.strRegKeyForStorePath, m_repoFile); + key.Flush(); + m_fSetRegistryValue = true; + } + if (key != null) + { + key.Close(); + key = null; + } + if (!String.IsNullOrEmpty(m_repoFile) && + File.Exists(m_repoFile) && + !File.Exists(m_repoFile + "-RESTOREME")) + { + File.Move(m_repoFile, m_repoFile + "-RESTOREME"); + } + if (!File.Exists(m_repoFile)) + m_fWroteRepoFile = true; + try + { + m_encConverters = new EncConverters(); + } + catch (Exception e) + { + Util.DebugWriteLine(this, e.Message); + } + Util.DebugWriteLine(this, "END"); + } + + /// -------------------------------------------------------------------- + /// + /// Initialization called before each test in this class ("fixture") is + /// run. + /// + /// -------------------------------------------------------------------- + [SetUp] + public void InitBeforeTest() + { + if (m_encConverters != null) + { + RemoveAnyAddedConverters(); + m_encConverters.Reinitialize(); + } + } + + /// -------------------------------------------------------------------- + /// + /// Cleanup called after each test in this class ("fixture") is run. + /// + /// -------------------------------------------------------------------- + [TearDown] + public void CleanupAfterTest() + { + if (m_encConverters != null) + { + RemoveAnyAddedConverters(); + } + } + + /// + /// Remove any added converters that are left behind due to a test + /// failure or other crash. + /// + private void RemoveAnyAddedConverters() + { + if (m_encConverters.ContainsKey("UnitTesting-ISO-8859-1")) + m_encConverters.Remove("UnitTesting-ISO-8859-1"); + if (m_encConverters.ContainsKey("UnitTesting-To-ISO-8859-1")) + m_encConverters.Remove("UnitTesting-To-ISO-8859-1"); + if (m_encConverters.ContainsKey("UnitTesting-Latin-Hebrew")) + m_encConverters.Remove ("UnitTesting-Latin-Hebrew"); + if (m_encConverters.ContainsKey("UnitTesting-Hebrew-Latin")) + m_encConverters.Remove ("UnitTesting-Hebrew-Latin"); + if (m_encConverters.ContainsKey("UnitTesting-Consonants->C")) + m_encConverters.Remove("UnitTesting-Consonants->C"); + if (m_encConverters.ContainsKey("UnitTesting-Vowels->V")) + m_encConverters.Remove("UnitTesting-Vowels->V"); + if (m_encConverters.ContainsKey("UnitTesting-Senufo-To-Unicode")) + m_encConverters.Remove("UnitTesting-Senufo-To-Unicode"); + if (m_encConverters.ContainsKey("UnitTesting-Unicode-To-Senufo")) + m_encConverters.Remove("UnitTesting-Unicode-To-Senufo"); + if (m_encConverters.ContainsKey("UnitTesting-Ann-To-Unicode")) + m_encConverters.Remove("UnitTesting-Ann-To-Unicode"); + if (m_encConverters.ContainsKey("UnitTesting-Unicode-To-Ann")) + m_encConverters.Remove("UnitTesting-Unicode-To-Ann"); + if (m_encConverters.ContainsKey("UnitTesting-ReverseString")) + m_encConverters.Remove("UnitTesting-ReverseString"); + + if (m_encConverters.ContainsKey("UnitTesting-From-CP_1252")) + m_encConverters.Remove("UnitTesting-From-CP_1252"); + if (m_encConverters.ContainsKey("UnitTesting-To-CP_1252")) + m_encConverters.Remove("UnitTesting-To-CP_1252"); + + if (m_encConverters.ContainsKey("UnitTesting-ThaiWordBreaker")) + m_encConverters.Remove("UnitTesting-ThaiWordBreaker"); + if (m_encConverters.ContainsKey("UnitTesting-AiKbConverter")) + m_encConverters.Remove("UnitTesting-AiKbConverter"); + + if (m_encConverters.ContainsKey(TestEncConverters.TechHindiSiteConverterFriendlyName)) + m_encConverters.Remove(TestEncConverters.TechHindiSiteConverterFriendlyName); + } + + /// -------------------------------------------------------------------- + /// + /// Global cleanup, called once after all tests in this class + /// ("fixture") have been run. + /// + /// -------------------------------------------------------------------- + [OneTimeTearDown] + public void CleanupForClass() + { + m_encConverters = null; + if (m_fWroteRepoFile) + { + File.Delete(m_repoFile); + m_fWroteRepoFile = false; + } + if (!String.IsNullOrEmpty(m_repoFile) && + File.Exists(m_repoFile + "-RESTOREME")) + { + if (File.Exists(m_repoFile)) + { + File.Delete(m_repoFile); // to overwrite file + } + File.Move(m_repoFile + "-RESTOREME", m_repoFile); + } + if (m_fSetRegistryValue) + { + RegistryKey key = Registry.CurrentUser.OpenSubKey(EncConverters.HKLM_PATH_TO_XML_FILE, true); + key.DeleteValue(EncConverters.strRegKeyForStorePath); + key.Flush(); + key.Close(); + m_fSetRegistryValue = false; + } + m_repoFile = null; + } + + private const string AzureOpenAIConverterFriendlyName = "ChatGptTranslator"; + + [Test] + [TestCase("Hindi;English;Translate from Hindi into English.", "यीशु ने यह भी कहा,", "Jesus also said this,")] + [TestCase(";;UseSystemPrompt: Translate from Hindi into English.", "परमेश्वर भेदभाव नहीं करता।", "God does not discriminate.")] + [TestCase("Hindi;English;with a \"free translation\" style aimed at high school students", @"यीशु ने यह भी कहा, +परमे‍‍श्वर मेरा पिता है।", @"Jesus also said this, +God is my father.")] + public void TestAzureOpenAiConverter(string converterSpec, string testInput, string testOutput) + { + // normally, these values get to the program that calls the AzureOpenAI endpoint via command line parameters that + // come from the exe's settings *.config file... but for tests, there isn't one, so, we can also send as env vars: + // BUT if you don't have a resource (and they're not easily available yet or free), then this test will fail anyway... + Environment.SetEnvironmentVariable(AzureOpenAiEncConverter.EnvVarNameEndPoint, "https://azure-openai-encconverter.openai.azure.com/"); + Environment.SetEnvironmentVariable(AzureOpenAiEncConverter.EnvVarNameDeploymentName, "gpt-translator-encconverter"); + Environment.SetEnvironmentVariable(AzureOpenAiEncConverter.EnvVarNameKey, "5bc..."); // change the key to the real value or this test will fail + + m_encConverters.AddConversionMap(AzureOpenAIConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, + AzureOpenAiEncConverter.ImplTypeSilAzureOpenAi, "UNICODE", "UNICODE", ProcessTypeFlags.Translation); + + var theEc = m_encConverters[AzureOpenAIConverterFriendlyName]; + + // do a forward conversion + var strOutput = theEc.Convert(testInput); + Assert.AreEqual(testOutput.ToUpper(), strOutput.ToUpper()); + } + + private const string BingTranslatorConverterFriendlyName = "BingTranslator"; + + // these tests may fail if the Bing Translator resource no longer has any remaining juice... OR (more likely) + // if they change the translation + [Test] + [TestCase(ProcessTypeFlags.Translation, "Translate;hi;en", "", "")] + [TestCase(ProcessTypeFlags.Translation, "Translate;hi;en", "यीशु ने यह भी कहा,", "Jesus also said,")] + [TestCase(ProcessTypeFlags.Translation, "Translate;;en", "यीशु ने यह भी कहा,", "Jesus also said,")] + [TestCase(ProcessTypeFlags.Translation, "Translate;en;zh-Hans", "This Israel Field Guide has been developed to help you get to know the beautiful country of Israel and also to encourage you to learn and experience the incredible Word of God and the truth of the events and doctrines that it presents.", "这本以色列实地指南旨在帮助您了解美丽的以色列国家,并鼓励您学习和体验上帝令人难以置信的话语以及它所呈现的事件和教义的真理。")] + [TestCase(ProcessTypeFlags.Translation | ProcessTypeFlags.Transliteration, "TranslateWithTransliterate;en;ar;;Latn", "God", "alleh")] + [TestCase(ProcessTypeFlags.Translation | ProcessTypeFlags.Transliteration, "TranslateWithTransliterate;;ar;;Latn", "God", "alleh")] + // [TestCase("TranslateWithTransliterate;;en;;Deva", "नहीं", "not")] // can't transliterate from an language=en result + // [TestCase("TranslateWithTransliterate;en;ar;;Arab", "God", "الله")] // you *can* do this, but there is no transliteration part of it (since the result is already in Arab script) + [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;hi;;Deva;Latn", "संसार", "sansar")] + [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;hi;;Latn;Deva", "sansar", "संसार")] + [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;ar;;Arab;Latn", "الله", "alleh")] + [TestCase(ProcessTypeFlags.Transliteration, "Transliterate;ar;;Latn;Arab", "alleh", "الله")] + // [TestCase("Transliterate;ar;;;Latn", "الله", "alleh")] // this doesn't work, because with Transliterate, you must specify the fromScript + [TestCase(ProcessTypeFlags.Translation, "DictionaryLookup;en;hi", "with", "साथ")] + [TestCase(ProcessTypeFlags.Translation, "DictionaryLookup;hi;en", "से", "%2%from%than%")] // when multiple results, return the ample disambiguation syntax (cf. AdaptIt lookup converter) + [TestCase(ProcessTypeFlags.Translation, "DictionaryLookup;en;hi", "schmaboogle", "")] // when there are no translations, it returns empty string + public void TestBingTransliteratorConverter(ProcessTypeFlags processType, string converterSpec, string testInput, string testOutput) { - var res = BingTranslatorEncConverter.GetCapabilities(); - Assert.Contains("Arabic العربية (ar)", res.translations.Select(t => t.ToString()).ToList()); - Assert.Contains("Hindi हिन्दी (hi) => (Latin लैटिन (Latn)) OR (Devanagari देवनागरी (Deva))", res.transliterations.Select(t => t.ToString()).ToList()); - Assert.Contains("Bulgarian Български (bg) => English (en)", res.dictionaryOptions.Select(t => t.ToString()).ToList()); - } - - [Test] - [TestCase("Hindi हिन्दी (hi)", "hi")] - [TestCase("French (Canada) Français (Canada) (fr-CA)", "fr-CA")] - [TestCase("Arabic العربية (ar)", "ar")] - [TestCase("Chinese Simplified 中文 (简体) (zh-Hans)", "zh-Hans")] - [TestCase("Fijian Na Vosa Vakaviti (fj)", "fj")] - [TestCase("Hmong Daw (mww)", "mww")] - [TestCase("Inuktitut (Latin) (iu-Latn)", "iu-Latn")] - [TestCase("Klingon (pIqaD) (tlh-Piqd)", "tlh-Piqd")] - [TestCase("Kurdish (Northern) Kurdî (Bakur) (kmr)", "kmr")] - [TestCase("Mongolian (Traditional) ᠮᠣᠩᠭᠣᠯ ᠬᠡᠯᠡ (mn-Mong)", "mn-Mong")] - [TestCase("Serbian (Cyrillic) Српски (ћирилица) (sr-Cyrl)", "sr-Cyrl")] - public void TestExtractingLangCode(string menuItem, string languageCodeExpected) + m_encConverters.AddConversionMap(BingTranslatorConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, + EncConverters.strTypeSILBingTranslator, "UNICODE", "UNICODE", + processType); + + var theEc = m_encConverters[BingTranslatorConverterFriendlyName]; + + // do a forward conversion + var strOutput = theEc.Convert(testInput); + Assert.AreEqual(testOutput, strOutput); + } + + [Test] + public void TestBingTranslatorGetCapabilities() + { + var res = BingTranslatorEncConverter.GetCapabilities(); + Assert.Contains("Arabic العربية (ar)", res.translations.Select(t => t.ToString()).ToList()); + Assert.Contains("Hindi हिन्दी (hi) => (Latin लैटिन (Latn)) OR (Devanagari देवनागरी (Deva))", res.transliterations.Select(t => t.ToString()).ToList()); + Assert.Contains("Bulgarian Български (bg) => English (en)", res.dictionaryOptions.Select(t => t.ToString()).ToList()); + } + + [Test] + [TestCase("Hindi हिन्दी (hi)", "hi")] + [TestCase("French (Canada) Français (Canada) (fr-CA)", "fr-CA")] + [TestCase("Arabic العربية (ar)", "ar")] + [TestCase("Chinese Simplified 中文 (简体) (zh-Hans)", "zh-Hans")] + [TestCase("Fijian Na Vosa Vakaviti (fj)", "fj")] + [TestCase("Hmong Daw (mww)", "mww")] + [TestCase("Inuktitut (Latin) (iu-Latn)", "iu-Latn")] + [TestCase("Klingon (pIqaD) (tlh-Piqd)", "tlh-Piqd")] + [TestCase("Kurdish (Northern) Kurdî (Bakur) (kmr)", "kmr")] + [TestCase("Mongolian (Traditional) ᠮᠣᠩᠭᠣᠯ ᠬᠡᠯᠡ (mn-Mong)", "mn-Mong")] + [TestCase("Serbian (Cyrillic) Српски (ћирилица) (sr-Cyrl)", "sr-Cyrl")] + public void TestExtractingLangCode(string menuItem, string languageCodeExpected) + { + var languageCodeActual = BingTranslatorAutoConfigDialog.ExtractCode(menuItem); + Assert.AreEqual(languageCodeExpected, languageCodeActual); + } + + private const string DeepLTranslatorConverterFriendlyName = "DeepLTranslator"; + + // these tests may fail if the DeepL Translator resource no longer has any remaining juice... OR (more likely) + // if they change the translation + [Test] + [TestCase(ProcessTypeFlags.Translation, "Translate;en;fr", "Hello, world!", "Bonjour à tous !")] + [TestCase(ProcessTypeFlags.Translation, "Translate;en;zh", "How are you?", "你好吗?")] + [TestCase(ProcessTypeFlags.Translation, "Translate;en;de;Less", "How are you?", "Wie geht es dir?")] + [TestCase(ProcessTypeFlags.Translation, "Translate;en;de;More", "How are you?", "Wie geht es Ihnen?")] + public void TestDeepLConverter(ProcessTypeFlags processType, string converterSpec, string testInput, string testOutput) + { + m_encConverters.AddConversionMap(DeepLTranslatorConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, + EncConverters.strTypeSILDeepLTranslator, "UNICODE", "UNICODE", + processType); + + var theEc = m_encConverters[DeepLTranslatorConverterFriendlyName]; + + // do a forward conversion + var strOutput = theEc.Convert(testInput); + Assert.AreEqual(testOutput, strOutput); + } + + [Test] + public async Task TestDeeplTranslatorGetCapabilities() { - var languageCodeActual = BingTranslatorAutoConfigDialog.ExtractCode(menuItem); - Assert.AreEqual(languageCodeExpected, languageCodeActual); - } - - private const string DeepLTranslatorConverterFriendlyName = "DeepLTranslator"; - - // these tests may fail if the DeepL Translator resource no longer has any remaining juice... OR (more likely) - // if they change the translation - [Test] - [TestCase(ProcessTypeFlags.Translation, "Translate;en;fr", "Hello, world!", "Bonjour à tous !")] - [TestCase(ProcessTypeFlags.Translation, "Translate;en;zh", "How are you?", "你好吗?")] - [TestCase(ProcessTypeFlags.Translation, "Translate;en;de;Less", "How are you?", "Wie geht es dir?")] - [TestCase(ProcessTypeFlags.Translation, "Translate;en;de;More", "How are you?", "Wie geht es Ihnen?")] - public void TestDeepLConverter(ProcessTypeFlags processType, string converterSpec, string testInput, string testOutput) - { - m_encConverters.AddConversionMap(DeepLTranslatorConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, - EncConverters.strTypeSILDeepLTranslator, "UNICODE", "UNICODE", - processType); - - var theEc = m_encConverters[DeepLTranslatorConverterFriendlyName]; - - // do a forward conversion - var strOutput = theEc.Convert(testInput); - Assert.AreEqual(testOutput, strOutput); - } - - [Test] - public async Task TestDeeplTranslatorGetCapabilities() - { var res = await DeepLTranslatorEncConverter.GetCapabilities(); Assert.IsNotNull(res); - Assert.Contains("en", res.languagesSource.Select(l => l.Code).ToList()); - Assert.Contains("fr", res.languagesTarget.Select(l => l.Code).ToList()); - Assert.Contains("fr", res.glossaryLanguagePairs.Select(l => l.SourceLanguageCode).ToList()); - Assert.Contains("de", res.glossaryLanguagePairs.Select(l => l.TargetLanguageCode).ToList()); - Assert.NotNull(res.usageLeft); - } - - private const string GoogleTranslatorConverterFriendlyName = "GoogleTranslator"; - - // these tests may fail if Google Translate resource no longer has any remaining juice... OR (more likely) - // if they change the translation - [Test] - [TestCase("en;fr", "Hello, world!", "Bonjour le monde!")] - [TestCase("en;zh", "This Israel Field Guide has been developed to help you get to know the beautiful country of Israel.", "这本以色列实地指南旨在帮助您了解以色列这个美丽的国家。")] - [TestCase("en;de", "How are you?", "Wie geht es dir?")] - public void TestGoogleConverter(string converterSpec, string testInput, string testOutput) - { - m_encConverters.AddConversionMap(GoogleTranslatorConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, - EncConverters.strTypeSILGoogleTranslator, "UNICODE", "UNICODE", - ProcessTypeFlags.Translation); - - var theEc = m_encConverters[GoogleTranslatorConverterFriendlyName]; - - // do a forward conversion - var strOutput = theEc.Convert(testInput); - Assert.AreEqual(testOutput, strOutput); - } - - [Test] - public async Task TestGoogleTranslateGetCapabilities() - { - var res = await GoogleTranslatorEncConverter.GetCapabilities(); - Assert.IsNotNull(res); + Assert.Contains("en", res.languagesSource.Select(l => l.Code).ToList()); + Assert.Contains("fr", res.languagesTarget.Select(l => l.Code).ToList()); + Assert.Contains("fr", res.glossaryLanguagePairs.Select(l => l.SourceLanguageCode).ToList()); + Assert.Contains("de", res.glossaryLanguagePairs.Select(l => l.TargetLanguageCode).ToList()); + Assert.NotNull(res.usageLeft); + } + + private const string GoogleTranslatorConverterFriendlyName = "GoogleTranslator"; + + // these tests may fail if Google Translate resource no longer has any remaining juice... OR (more likely) + // if they change the translation + [Test] + [TestCase("en;fr", "Hello, world!", "Bonjour le monde!")] + [TestCase("en;zh", "This Israel Field Guide has been developed to help you get to know the beautiful country of Israel.", "这本以色列实地指南旨在帮助您了解以色列这个美丽的国家。")] + [TestCase("en;de", "How are you?", "Wie geht es dir?")] + public void TestGoogleConverter(string converterSpec, string testInput, string testOutput) + { + m_encConverters.AddConversionMap(GoogleTranslatorConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, + EncConverters.strTypeSILGoogleTranslator, "UNICODE", "UNICODE", + ProcessTypeFlags.Translation); + + var theEc = m_encConverters[GoogleTranslatorConverterFriendlyName]; + + // do a forward conversion + var strOutput = theEc.Convert(testInput); + Assert.AreEqual(testOutput, strOutput); + } + + [Test] + public async Task TestGoogleTranslateGetCapabilities() + { + var res = await GoogleTranslatorEncConverter.GetCapabilities(); + Assert.IsNotNull(res); var languagesSupported = res.Select(l => l.Code).ToList(); Assert.Contains("en", languagesSupported); - Assert.Contains("fr", languagesSupported); - Assert.Contains("de", languagesSupported); - Assert.Contains("doi", languagesSupported); - } + Assert.Contains("fr", languagesSupported); + Assert.Contains("de", languagesSupported); + Assert.Contains("doi", languagesSupported); + } #if Disable - [Test] - public async Task TestGoogleCloudBillingAccountQuery() - { - var res = await GoogleTranslatorAutoConfigDialog.GetUsage(); - Assert.IsNotNull(res); - } + [Test] + public async Task TestGoogleCloudBillingAccountQuery() + { + var res = await GoogleTranslatorAutoConfigDialog.GetUsage(); + Assert.IsNotNull(res); + } #endif - } + } } diff --git a/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj b/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj index 4b34a275..35f4a363 100644 --- a/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj +++ b/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj @@ -67,7 +67,7 @@ DEBUG; true full - AnyCPU + x86 latest prompt AllRules.ruleset @@ -77,7 +77,7 @@ $(SolutionDir)output\Win32\$(Configuration)\ true full - AnyCPU + x86 latest prompt AllRules.ruleset @@ -99,23 +99,23 @@ ..\..\packages\Google.Api.Gax.Rest.4.4.0\lib\net462\Google.Api.Gax.Rest.dll - - ..\..\packages\Google.Apis.1.61.0\lib\net45\Google.Apis.dll + + ..\..\packages\Google.Apis.1.62.1\lib\net45\Google.Apis.dll - - ..\..\packages\Google.Apis.Auth.1.61.0\lib\net461\Google.Apis.Auth.dll + + ..\..\packages\Google.Apis.Auth.1.62.1\lib\net461\Google.Apis.Auth.dll - - ..\..\packages\Google.Apis.Auth.1.61.0\lib\net461\Google.Apis.Auth.PlatformServices.dll + + ..\..\packages\Google.Apis.Auth.1.62.1\lib\net461\Google.Apis.Auth.PlatformServices.dll - - ..\..\packages\Google.Apis.Core.1.61.0\lib\net45\Google.Apis.Core.dll + + ..\..\packages\Google.Apis.Core.1.62.1\lib\net45\Google.Apis.Core.dll - - ..\..\packages\Google.Apis.1.61.0\lib\net45\Google.Apis.PlatformServices.dll + + ..\..\packages\Google.Apis.1.62.1\lib\net45\Google.Apis.PlatformServices.dll - - ..\..\packages\Google.Apis.Translate.v2.1.61.0.875\lib\net45\Google.Apis.Translate.v2.dll + + ..\..\packages\Google.Apis.Translate.v2.1.62.0.875\lib\net45\Google.Apis.Translate.v2.dll ..\..\packages\Google.Cloud.Translation.V2.3.2.0\lib\net462\Google.Cloud.Translation.V2.dll @@ -175,12 +175,15 @@ - - ..\..\packages\System.Diagnostics.DiagnosticSource.7.0.0-preview.6.22324.4\lib\net462\System.Diagnostics.DiagnosticSource.dll + + ..\..\packages\System.Diagnostics.DiagnosticSource.7.0.2\lib\net462\System.Diagnostics.DiagnosticSource.dll ..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + ..\..\packages\System.Memory.Data.7.0.0\lib\net462\System.Memory.Data.dll + @@ -190,7 +193,10 @@ ..\..\packages\System.Runtime.CompilerServices.Unsafe.7.0.0-preview.2.22152.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll - ..\..\packages\System.Text.Encodings.Web.7.0.0-preview.6.22324.4\lib\net462\System.Text.Encodings.Web.dll + ..\..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll + + + ..\..\packages\System.Text.Json.7.0.3\lib\net462\System.Text.Json.dll ..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll diff --git a/src/TestEncCnvtrs/app.config b/src/TestEncCnvtrs/app.config index e089836a..d3e121c0 100644 --- a/src/TestEncCnvtrs/app.config +++ b/src/TestEncCnvtrs/app.config @@ -14,17 +14,25 @@ + + + + + + + + - + @@ -40,19 +48,19 @@ - + - + - + - + diff --git a/src/TestEncCnvtrs/packages.config b/src/TestEncCnvtrs/packages.config index 315a65d0..0d897a40 100644 --- a/src/TestEncCnvtrs/packages.config +++ b/src/TestEncCnvtrs/packages.config @@ -2,17 +2,24 @@ - - - - + + + + + + + + + + + \ No newline at end of file From 5eb72ac3a284cf1e5b359e6c34ac8dd665dbb05a Mon Sep 17 00:00:00 2001 From: bobeaton Date: Thu, 26 Oct 2023 08:01:33 -0500 Subject: [PATCH 003/113] don't bother sending an empty string to the online translators. --- .../BingTranslator/BingTranslatorEncConverter.cs | 4 +++- .../DeepLTranslator/DeepLTranslatorEncConverter.cs | 4 +++- .../GoogleTranslator/GoogleTranslatorEncConverter.cs | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/EcTranslators/BingTranslator/BingTranslatorEncConverter.cs b/src/EcTranslators/BingTranslator/BingTranslatorEncConverter.cs index 41e7e4b2..26edafe9 100644 --- a/src/EcTranslators/BingTranslator/BingTranslatorEncConverter.cs +++ b/src/EcTranslators/BingTranslator/BingTranslatorEncConverter.cs @@ -214,7 +214,9 @@ ref int rnOutLen // here's our input string var strInput = new string(caIn); - var strOutput = CallBingTranslator(strInput).Result; + var strOutput = String.IsNullOrEmpty(strInput) + ? strInput + : CallBingTranslator(strInput).Result; StringToProperByteStar(strOutput, lpOutBuffer, ref rnOutLen); } diff --git a/src/EcTranslators/DeepLTranslator/DeepLTranslatorEncConverter.cs b/src/EcTranslators/DeepLTranslator/DeepLTranslatorEncConverter.cs index 42ab725e..1c07fead 100644 --- a/src/EcTranslators/DeepLTranslator/DeepLTranslatorEncConverter.cs +++ b/src/EcTranslators/DeepLTranslator/DeepLTranslatorEncConverter.cs @@ -260,7 +260,9 @@ ref int rnOutLen // here's our input string var strInput = new string(caIn); - var strOutput = CallDeepLTranslator(strInput).Result; + var strOutput = String.IsNullOrEmpty(strInput) + ? strInput + : CallDeepLTranslator(strInput).Result; StringToProperByteStar(strOutput, lpOutBuffer, ref rnOutLen); } diff --git a/src/EcTranslators/GoogleTranslator/GoogleTranslatorEncConverter.cs b/src/EcTranslators/GoogleTranslator/GoogleTranslatorEncConverter.cs index 6c1d45b0..4d5576bb 100644 --- a/src/EcTranslators/GoogleTranslator/GoogleTranslatorEncConverter.cs +++ b/src/EcTranslators/GoogleTranslator/GoogleTranslatorEncConverter.cs @@ -179,7 +179,9 @@ ref int rnOutLen // here's our input string var strInput = new string(caIn); - var strOutput = CallGoogleTranslator(strInput).Result; + var strOutput = String.IsNullOrEmpty(strInput) + ? strInput + : CallGoogleTranslator(strInput).Result; StringToProperByteStar(strOutput, lpOutBuffer, ref rnOutLen); } From b0fc8dbada5417b5208f53c81cd5e0a5c761ad65 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Thu, 26 Oct 2023 08:02:49 -0500 Subject: [PATCH 004/113] Allow the EncConverter config dialog's About box to be an http address, rather than only local .htm files (ultimately, unused, bkz Microsoft, whose webpage I wanted to use, blocks the use of Firefox, but not a bad change). Also upgraded to a newer version of WebView2 to see if that fixes the incompatibility with multiple clients using different versions of the runtime (still not fixed, but no need to revert) --- src/EncCnvtrs/AutoConfigDialog.cs | 6 ++++-- src/EncCnvtrs/EncCnvtrs 2010.csproj | 16 ++++++++-------- src/EncCnvtrs/EncCnvtrs.resx | 2 +- src/EncCnvtrs/packages.config | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/EncCnvtrs/AutoConfigDialog.cs b/src/EncCnvtrs/AutoConfigDialog.cs index 022203ab..61979480 100755 --- a/src/EncCnvtrs/AutoConfigDialog.cs +++ b/src/EncCnvtrs/AutoConfigDialog.cs @@ -131,9 +131,11 @@ bool bIsInRepository var strXmlFilePath = (string)keyRoot.GetValue("RootDir"); if (String.IsNullOrEmpty(strXmlFilePath)) throw new ApplicationException("The 'RootDir' registry key is not defined!? Perhaps the application needs to be re-installed. Ask the developer."); - strXmlFilePath = Path.Combine(strXmlFilePath, Path.Combine(@"Help", strHtmlFileName)); + if (strHtmlFileName.StartsWith("http")) + strXmlFilePath = strHtmlFileName; + else + strXmlFilePath = Path.Combine(strXmlFilePath, Path.Combine(@"Help", strHtmlFileName)); System.Diagnostics.Debug.WriteLine(strXmlFilePath); - System.Diagnostics.Debug.Assert(System.IO.File.Exists(strXmlFilePath), String.Format("Cannot find '{0}'. If this is a development machine, you need to add the following reg key to see the About help files: HLKM\\SOFTWARE\\SIL\\SilEncConverters40\\[RootDir] = '' along with a trailing slash (e.g. \"C:\\fw\\lib\\release\\\")", strHtmlFileName)); this.webBrowser.Navigate(strXmlFilePath); } #if DEBUG diff --git a/src/EncCnvtrs/EncCnvtrs 2010.csproj b/src/EncCnvtrs/EncCnvtrs 2010.csproj index e40a64fe..b3261290 100644 --- a/src/EncCnvtrs/EncCnvtrs 2010.csproj +++ b/src/EncCnvtrs/EncCnvtrs 2010.csproj @@ -135,14 +135,14 @@ - - ..\..\packages\Microsoft.Web.WebView2.1.0.1938.49\lib\net45\Microsoft.Web.WebView2.Core.dll + + ..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\lib\net45\Microsoft.Web.WebView2.Core.dll - - ..\..\packages\Microsoft.Web.WebView2.1.0.1938.49\lib\net45\Microsoft.Web.WebView2.WinForms.dll + + ..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\lib\net45\Microsoft.Web.WebView2.WinForms.dll - - ..\..\packages\Microsoft.Web.WebView2.1.0.1938.49\lib\net45\Microsoft.Web.WebView2.Wpf.dll + + ..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\lib\net45\Microsoft.Web.WebView2.Wpf.dll ..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll @@ -512,12 +512,12 @@ - + - + \ No newline at end of file diff --git a/src/EncCnvtrs/EncCnvtrs.resx b/src/EncCnvtrs/EncCnvtrs.resx index 4a9bb567..4fe2131f 100755 --- a/src/EncCnvtrs/EncCnvtrs.resx +++ b/src/EncCnvtrs/EncCnvtrs.resx @@ -1,4 +1,4 @@ - + + + + + + + + + + + + + + + + + diff --git a/installer/PythonEcMM/PythonEc_MergeModule.wxs b/installer/PythonEcMM/PythonEc_MergeModule.wxs index 81319a8f..a72e96d4 100644 --- a/installer/PythonEcMM/PythonEc_MergeModule.wxs +++ b/installer/PythonEcMM/PythonEc_MergeModule.wxs @@ -7,14 +7,20 @@ - - + + + + + + @@ -74,6 +80,24 @@ + + + + + + + + + + + + + + + + + diff --git a/redist/EC/Plugins/PythonEC 4.0.0.0 Plugin Details.xml b/redist/EC/Plugins/PythonEC 4.0.0.0 Plugin Details.xml index 5f0cedba..f86c90f9 100755 --- a/redist/EC/Plugins/PythonEC 4.0.0.0 Plugin Details.xml +++ b/redist/EC/Plugins/PythonEC 4.0.0.0 Plugin Details.xml @@ -8,5 +8,13 @@ DefiningExtension=".py" AssemblyReference="PyScriptEC, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null" /> - + + diff --git a/redist/Help/Python_3_Script_Plug-in_About_box.htm b/redist/Help/Python_3_Script_Plug-in_About_box.htm new file mode 100644 index 00000000..e932c0ff --- /dev/null +++ b/redist/Help/Python_3_Script_Plug-in_About_box.htm @@ -0,0 +1,1553 @@ + + + + + + + + + + +Python 3 Script + + + + + + + + + +
+ +

Python 3 Script

+ +

This converter type allows you to use Python functions for +Unicode text processing. For example, you could have the following Python function +to return the Unicode code point names for all the characters in the input +string (e.g. the input string, ő , would return "LATIN SMALL LETTER O; COMBINING DOUBLE ACUTE ACCENT; "):

+ +

 

+ +

# return the UnicodeName of input string

+ +

import unicodedata

+ +

def Convert(u):

+ +

if not +isinstance(u, unicode):

+ +

raise +UnicodeError(u'Input Data is not a Unicode string! (%s)' % u)

+ +

else:

+ +

r = u''

+ +

for ch in +u:

+ +

r += +'%s; ' % unicodedata.name(ch)

+ +

return r

+ +

 

+ +

The directory of the Python script gets added to sys.path by EncConverters. This makes it easy to import another python +script in the same directory. For +example, a script could say:

+ +

 

+ +

import +script2
+
def +Convert(u):
+    return script2.enToGarhwali(u)

+ +

 

+ +

If there was a script2.py +in the same folder defined, for example, as:

+ +

 

+ +

def +enToGarhwali(u):

+ +

if u.lower() in (u"what's this?", +u"what is this?"):

+ +

return u"yu kyaa chh?"

+ +

else:

+ +

return u"(could not +translate)"

+ +

 

+ +
+ +

To use this transducer, you must have a Python distribution +(v. 3.*) installed on your machine. You can download a free Python +distributions, such as Python 3.12, from https://www.python.org/downloads.

+ +
+ +

Setup Tab

+ +

Here is the setup tab for the Python 3 Script +EncConverter:

+ +

+ +

Figure 1: Python Script Setup

+ +

 

+ +

1.      +Browse +(using the upper Browse... button) for the Python script file that +implements a function named Convert as shown in +the above examples.

+ +

2.      +Browse (using the lower Browse... button) for the python3 DLL file (e.g. python312.dll) +located in the folder you installed your python distribution in.

+ +

After +configuring the path to the script and Python DLL files, you can click the Apply button to accept the configuration.

+ +

Also shown are the following options:

+ +

3.      If you want the Python function to be +permanently added to the System Repository, then click the Save in System +Repository button.

+ +

4.      +You can +click on the Test Area tab in order to test the converter with +some sample data.

+ +

Saving the converter in the System Repository:

+ +

By default, if you click the Apply +or OK buttons, the configured converter will +be returned to the client application as a temporary converter for temporary +use. Once the client application (e.g. FieldWorks +or Word) is closed or releases the converter, it +will no longer be available. If you want the converter to be permanently +available to client applications, then you must explicitly add it to the System Repository using the Save +in System Repository button.

+ +

When you click this button, the following dialog box will +be displayed to query for a friendly name by +which the converter will be known in client applications:

+ +

+ +

 

+ +

For the Python Script converter, the default name will be the +file name of the Python script containing Convert function. However, you can +change it to something more descriptive if desired.

+ +

The Advanced tab can be +used to enter further, optional information about this converter which is also +put into the System Repository and can be used +by various client applications. Clicking this tab will bring up the following +dialog box:

+ +

+ +

 

+ +

Though these values are not necessary for the operation of +the converter, they can be helpful to various client applications. For example, +the Clipboard EncConverter can be configured to +filter the list of displayed converters based on the Encoding +Name and/or the Transduction Type +configured here.

+ +
+ + + + diff --git a/redist/Help/Python_3_Script_Plug-in_About_box_files/colorschememapping.xml b/redist/Help/Python_3_Script_Plug-in_About_box_files/colorschememapping.xml new file mode 100644 index 00000000..6a0069cd --- /dev/null +++ b/redist/Help/Python_3_Script_Plug-in_About_box_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Python_3_Script_Plug-in_About_box_files/filelist.xml b/redist/Help/Python_3_Script_Plug-in_About_box_files/filelist.xml new file mode 100644 index 00000000..cb808d2a --- /dev/null +++ b/redist/Help/Python_3_Script_Plug-in_About_box_files/filelist.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/redist/Help/Python_3_Script_Plug-in_About_box_files/header.htm b/redist/Help/Python_3_Script_Plug-in_About_box_files/header.htm new file mode 100644 index 00000000..b24777d7 --- /dev/null +++ b/redist/Help/Python_3_Script_Plug-in_About_box_files/header.htm @@ -0,0 +1,59 @@ + + + + + + + + + + + + +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ + + + diff --git a/redist/Help/Python_3_Script_Plug-in_About_box_files/image004.jpg b/redist/Help/Python_3_Script_Plug-in_About_box_files/image004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8fc625753ed2fabedb3c4073cc0316fcc61a3bb7 GIT binary patch literal 22503 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 Z0)eWm<0H+qyLd_W8H)s}J&RG}{|9(9#$Esb literal 0 HcmV?d00001 diff --git a/redist/Help/Python_3_Script_Plug-in_About_box_files/image010.jpg b/redist/Help/Python_3_Script_Plug-in_About_box_files/image010.jpg new file mode 100644 index 0000000000000000000000000000000000000000..44e806c3d4b4d3b3e0c5a889d66db8f4c4d8e80c GIT binary patch literal 30209 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 M791+Z_~rHA07kO&lK=n! literal 0 HcmV?d00001 diff --git a/redist/Help/Python_3_Script_Plug-in_About_box_files/themedata.thmx b/redist/Help/Python_3_Script_Plug-in_About_box_files/themedata.thmx new file mode 100644 index 0000000000000000000000000000000000000000..c2dd8c12f543e366e400e460e992377dd3c1ad27 GIT binary patch literal 3104 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 Tj><>?03G#qqE?RseSiBCYAr;+ literal 0 HcmV?d00001 diff --git a/redist/MapsTables/PythonExamples/ReverseString.py b/redist/MapsTables/PythonExamples/ReverseString.py index 5f7b3f37..e69c6d01 100644 --- a/redist/MapsTables/PythonExamples/ReverseString.py +++ b/redist/MapsTables/PythonExamples/ReverseString.py @@ -14,18 +14,18 @@ def Convert(s): ## Warning: The following testing code will not work on Python 3. result = Convert(b'mop') expected = b'pom' - print b"result: %s" % repr(result) + print(b"result: %s" % repr(result)) if result != expected: - print b"unexpected result; expected %s" % repr(expected) + print(b"unexpected result; expected %s" % repr(expected)) exit() ui = u"மோப" # Tamil Ma + Oo + Pa - print u"sending: %s " % repr(ui) + print(u"sending: %s " % repr(ui)) result = Convert(ui) - print u"result: %s" % repr(result) + print(u"result: %s" % repr(result)) expected = u"போம" # Tamil Pa + Oo + Ma if result == expected: - print "ok" + print("ok") else: - print u"unexpected result; expected %s" % repr(expected) + print(u"unexpected result; expected %s" % repr(expected)) diff --git a/redist/MapsTables/PythonExamples/ToLowerCase.py b/redist/MapsTables/PythonExamples/ToLowerCase.py index f8339458..129c0ea3 100644 --- a/redist/MapsTables/PythonExamples/ToLowerCase.py +++ b/redist/MapsTables/PythonExamples/ToLowerCase.py @@ -8,9 +8,9 @@ def Convert(bytesInput): ## Warning: The following testing code will not work on Python 3. result = Convert(b'ASdG') expected = b'asdg' - print b"result: %s" % repr(result) + print(b"result: %s" % repr(result)) if result == expected: - print "ok" + print("ok") else: - print b"unexpected result; expected %s" % repr(expected) + print(b"unexpected result; expected %s" % repr(expected)) diff --git a/redist/MapsTables/PythonExamples/ToNfc.py b/redist/MapsTables/PythonExamples/ToNfc.py index e1bbc6a6..f54a4990 100644 --- a/redist/MapsTables/PythonExamples/ToNfc.py +++ b/redist/MapsTables/PythonExamples/ToNfc.py @@ -12,12 +12,12 @@ def Convert(u): if __name__ == '__main__': ## Warning: The following testing code will not work on Python 3. uInput = u"Ę" # NFD string - print u"sending: %s" % repr(uInput) + print(u"sending: %s" % repr(uInput)) result = Convert(uInput) - print u"result: %s" % repr(result) + print(u"result: %s" % repr(result)) expected = u"Ę" # NFC string if result == expected: - print "ok" + print("ok") else: - print u"unexpected result; expected %s" % repr(expected) + print(u"unexpected result; expected %s" % repr(expected)) diff --git a/redist/MapsTables/PythonExamples/ToNfd.py b/redist/MapsTables/PythonExamples/ToNfd.py index b567bc80..0a945d78 100644 --- a/redist/MapsTables/PythonExamples/ToNfd.py +++ b/redist/MapsTables/PythonExamples/ToNfd.py @@ -12,12 +12,12 @@ def Convert(u): if __name__ == '__main__': ## Warning: The following testing code will not work on Python 3. uInput = u"क़" # NFC string - print u"sending: %s" % repr(uInput) + print(u"sending: %s" % repr(uInput)) result = Convert(uInput) - print u"result: %s" % repr(result) + print(u"result: %s" % repr(result)) expected = u"क़" # NFD string if result == expected: - print "ok" + print("ok") else: - print u"unexpected result; expected %s" % repr(expected) + print(u"unexpected result; expected %s" % repr(expected)) diff --git a/redist/MapsTables/PythonExamples/ToUnicodeNames.py b/redist/MapsTables/PythonExamples/ToUnicodeNames.py index 78885b73..189b49e0 100644 --- a/redist/MapsTables/PythonExamples/ToUnicodeNames.py +++ b/redist/MapsTables/PythonExamples/ToUnicodeNames.py @@ -18,11 +18,11 @@ def Convert(u): if __name__ == '__main__': ## Warning: The following testing code will not work on Python 3. uInput = u"क़" - print u"sending: %s" % repr(uInput) + print(u"sending: %s" % repr(uInput)) result = Convert(uInput) - print "result: %s" % repr(result) + print("result: %s" % repr(result)) expected = "DEVANAGARI LETTER KA; DEVANAGARI SIGN NUKTA; " if result == expected: - print "ok" + print("ok") else: - print "unexpected result; expected %s" % repr(expected) + print("unexpected result; expected %s" % repr(expected)) diff --git a/redist/MapsTables/PythonExamples/ToUpperCase.py b/redist/MapsTables/PythonExamples/ToUpperCase.py index b3dbf16e..b21911d3 100644 --- a/redist/MapsTables/PythonExamples/ToUpperCase.py +++ b/redist/MapsTables/PythonExamples/ToUpperCase.py @@ -8,8 +8,8 @@ def Convert(bytesInput): ## Warning: The following testing code will not work on Python 3. result = Convert(b'asdg') expected = b'ASDG' - print b"result: %s" % repr(result) + print(b"result: %s" % repr(result)) if result == expected: - print "ok" + print("ok") else: - print b"unexpected result; expected %s" % repr(expected) + print(b"unexpected result; expected %s" % repr(expected)) diff --git a/src/EncCnvtrs/EncConverters.cs b/src/EncCnvtrs/EncConverters.cs index 40fa2003..91141be2 100755 --- a/src/EncCnvtrs/EncConverters.cs +++ b/src/EncCnvtrs/EncConverters.cs @@ -37,10 +37,10 @@ public class EncConverters : Hashtable, IEncConverters #region Const Definitions // private registry access key string constants public const string BY_PROCESS_TYPE = "ByProcessType"; - public const string strInstallerLocationRegKey = @"SOFTWARE\SIL\SilEncConverters40\Installer"; - public const string strInstallerPathKey = "InstallerPath"; + public const string strInstallerLocationRegKey = @"SOFTWARE\SIL\SilEncConverters40\Installer"; + public const string strInstallerPathKey = "InstallerPath"; #if UseXmlFilesForPlugins - public const string SEC_ROOT_KEY = @"SOFTWARE\SIL\SilEncConverters40"; + public const string SEC_ROOT_KEY = @"SOFTWARE\SIL\SilEncConverters40"; #if !PluginsInEachFolder public const string CstrDefPluginFolderEc = "EC"; public const string CstrDefPluginFolderPlugins = "Plugins"; @@ -62,11 +62,11 @@ public class EncConverters : Hashtable, IEncConverters public const string strRegKeyForSelfRegistering = "RegisterSelf"; internal const string strShowToolTipsStateKey = "ShowToolTips"; internal const string CstrUseGeckoRegKey = "UseMozilla"; - internal const string CstrUseEdgeRegKey = "UseEdge"; + internal const string CstrUseEdgeRegKey = "UseEdge"; - // implement types define in EncCnvtrs.dll (public so users can use them in .Net - // code rather than hard-coding the strings) - public const string strTypeImplCOM = "COM"; + // implement types define in EncCnvtrs.dll (public so users can use them in .Net + // code rather than hard-coding the strings) + public const string strTypeImplCOM = "COM"; public const string strTypeSILcc = "SIL.cc"; public const string strTypeSILtec = "SIL.tec"; public const string strTypeSILtecForm = "SIL.tecForm"; @@ -77,17 +77,18 @@ public class EncConverters : Hashtable, IEncConverters public const string strTypeSILicuConv = "ICU.conv"; public const string strTypeSILicuRegex = "ICU.regex"; public const string strTypeSILPyScript = "SIL.PyScript"; + public const string strTypeSILPy3Script = "SIL.Py3Script"; public const string strTypeSILPerlExpression = "SIL.PerlExpression"; public const string strTypeSILfallback = "SIL.fallback"; public const string strTypeSILadaptit = "SIL.AdaptItKB"; public const string strTypeSILadaptitGuesser = "SIL.AdaptItKBGuesser"; public const string strTypeSILtechHindiSite = "SIL.TechHindiWebPage"; public const string strTypeSILBingTranslator = "SIL.BingTranslator"; - public const string strTypeSILGoogleTranslator = "SIL.GoogleTranslator"; + public const string strTypeSILGoogleTranslator = "SIL.GoogleTranslator"; public const string strTypeSILDeepLTranslator = "SIL.DeepLTranslator"; public const string strTypeSILAzureOpenAiTranslator = "SIL.AzureOpenAI"; - public const string cstrTempConverterPrefix = "Temporary Converter"; + public const string cstrTempConverterPrefix = "Temporary Converter"; // default values for XML file attributes public const string HKLM_PATH_TO_XML_FILE = @"SOFTWARE\SIL\EncodingConverterRepository"; @@ -433,17 +434,17 @@ protected void GetConversionEnginesSupported() // read the XML details mappingRegistry.platformRow aPlatformRow = file.platform.FindByname(strTypeImplCOM); - if (aPlatformRow != null) - { - foreach (mappingRegistry.implementRow aImplRow in aPlatformRow.GetimplementRows()) - { - mapImplementTypesUse[aImplRow.type] = aImplRow.use; - int priority = ((aImplRow.IspriorityNull()) ? cnDefImplPriority : aImplRow.priority); - m_mapImplementTypesPriority[aImplRow.type] = priority; - } - } - - InsureImplementationsRow(file); + if (aPlatformRow != null) + { + foreach (mappingRegistry.implementRow aImplRow in aPlatformRow.GetimplementRows()) + { + mapImplementTypesUse[aImplRow.type] = aImplRow.use; + int priority = ((aImplRow.IspriorityNull()) ? cnDefImplPriority : aImplRow.priority); + m_mapImplementTypesPriority[aImplRow.type] = priority; + } + } + + InsureImplementationsRow(file); mappingRegistry.implementationsRow aImplsRow = file.implementations[0]; // now open and read the information about which plug-ins are installed (based on the @@ -468,17 +469,17 @@ protected void GetConversionEnginesSupported() if (String.IsNullOrEmpty(strPluginXmlFilesFolder)) #if !PluginsInEachFolder - { - // Argh... - // in v4.0, we have the assemblies in each our own install folders. But the - // Fieldworks instance can't use the instance of this assembly installed as - // part of SEC, for example. So the whole, "Let's try to use the newer version - // of the assembly installed by the other guy" doesn't work. Therefore, we - // also no longer want to. Each client will put the plugins in a - // \EC\Plugins folder - Debug.WriteLine("EncConverters: Falling back to assembly folder"); - strPluginXmlFilesFolder = PlugInFolder; - } + { + // Argh... + // in v4.0, we have the assemblies in each our own install folders. But the + // Fieldworks instance can't use the instance of this assembly installed as + // part of SEC, for example. So the whole, "Let's try to use the newer version + // of the assembly installed by the other guy" doesn't work. Therefore, we + // also no longer want to. Each client will put the plugins in a + // \EC\Plugins folder + Debug.WriteLine("EncConverters: Falling back to assembly folder"); + strPluginXmlFilesFolder = PlugInFolder; + } #else { strPluginXmlFilesFolder = Util.CommonAppDataPath() + strDefPluginFolder; @@ -486,7 +487,7 @@ protected void GetConversionEnginesSupported() strPluginXmlFilesFolder += strDefPluginFolderVersionPrefix + typeof(IEncConverter).Assembly.GetName().Version.ToString(); #endif - Debug.Assert(Directory.Exists(strPluginXmlFilesFolder), String.Format("Can't find the plug-in folder, '{0}'", strPluginXmlFilesFolder)); + Debug.Assert(Directory.Exists(strPluginXmlFilesFolder), String.Format("Can't find the plug-in folder, '{0}'", strPluginXmlFilesFolder)); string[] astrPluginXmlFiles = Directory.GetFiles(strPluginXmlFilesFolder, "*.xml"); Debug.Assert(astrPluginXmlFiles.Length > 0, String.Format(@"You don't have any plug-ins installed (e.g. {0}\SilEncConverters40 Plugin Details.xml)", strPluginXmlFilesFolder)); @@ -582,9 +583,9 @@ protected void GetConversionEnginesSupported() { strProgId = (string)m_mapImplTypeToProgId[strImplementationType]; - // see if one or the other has a higher priority. (it might not be in there yet, if we're just building an initial repo) - if (!m_mapImplementTypesPriority.ContainsKey(strImplementationType)) - continue; + // see if one or the other has a higher priority. (it might not be in there yet, if we're just building an initial repo) + if (!m_mapImplementTypesPriority.ContainsKey(strImplementationType)) + continue; int nNewPriority = aDetailsRow.Priority; int nExistingPriority = (int)m_mapImplementTypesPriority[strImplementationType]; @@ -715,25 +716,25 @@ protected void GetConversionEnginesSupported() WriteRepositoryFile(file); } - /// - /// Returns the folder we expect to find the plug-ins describing which assemblies the various implementations are in - /// - private string PlugInFolder - { - get - { - return Path.Combine(Path.Combine(GetRunningFolder, - CstrDefPluginFolderEc), - CstrDefPluginFolderPlugins); - } - } - - /// - /// Get the folder the executing assembly comes from. On Windows .Net, Location - /// will likely point to a "shadow copy". We want the original location, so we use - /// CodeBase instead (even though the URI must be dealt with). - /// - protected static string GetRunningFolder + /// + /// Returns the folder we expect to find the plug-ins describing which assemblies the various implementations are in + /// + private string PlugInFolder + { + get + { + return Path.Combine(Path.Combine(GetRunningFolder, + CstrDefPluginFolderEc), + CstrDefPluginFolderPlugins); + } + } + + /// + /// Get the folder the executing assembly comes from. On Windows .Net, Location + /// will likely point to a "shadow copy". We want the original location, so we use + /// CodeBase instead (even though the URI must be dealt with). + /// + protected static string GetRunningFolder { get { @@ -1996,7 +1997,7 @@ public override void Remove(object mapName) public void RemoveNonPersist(object mapName) { Util.DebugWriteLine(this, "BEGIN"); - // first see if this name is a concatenation of mappingName+implementation + // first see if this name is a concatenation of mappingName+implementation string sImplementType; string strMapName = StringMapNameFromObject(mapName); string strConverterName = GetMappingName(strMapName, out sImplementType); @@ -2420,32 +2421,32 @@ public IEncConverter InstantiateIEncConverter(string strProgID, string strAssemb { Util.DebugWriteLine(this, "Getting from assembly."); - ObjectHandle ohndl; - try - { - ohndl = Activator.CreateInstance(strAssemblySpec, strProgID); - rConverter = (IEncConverter)ohndl.Unwrap(); - } - catch (Exception ex) - { - // see if we can load the assembly from an installation of SILConverters + ObjectHandle ohndl; + try + { + ohndl = Activator.CreateInstance(strAssemblySpec, strProgID); + rConverter = (IEncConverter)ohndl.Unwrap(); + } + catch (Exception ex) + { + // see if we can load the assembly from an installation of SILConverters // strAssemblySpec = e.g. "SilEncConverters40, Version=4.0.0.0, Culture=neutral, PublicKeyToken=f1447bae1e63f485" - var index = strAssemblySpec.IndexOf(','); - if (index > 0) - { - var assemblyName = strAssemblySpec.Substring(0, index); - var keyInstallLocation = Registry.LocalMachine.OpenSubKey(strInstallerLocationRegKey); - if (keyInstallLocation != null) - { - var installPath = (string)keyInstallLocation.GetValue(strInstallerPathKey); - var assemblyFileSpec = Path.Combine(Path.GetDirectoryName(installPath), $"{assemblyName}.dll"); - var assembly = Assembly.LoadFrom(assemblyFileSpec); - var type = assembly.GetType(strProgID); - Util.DebugWriteLine(this, ex.Message + $" So trying to get {strProgID} from {assemblyFileSpec} instead"); - rConverter = (IEncConverter) Activator.CreateInstance(type); - } - } - } + var index = strAssemblySpec.IndexOf(','); + if (index > 0) + { + var assemblyName = strAssemblySpec.Substring(0, index); + var keyInstallLocation = Registry.LocalMachine.OpenSubKey(strInstallerLocationRegKey); + if (keyInstallLocation != null) + { + var installPath = (string)keyInstallLocation.GetValue(strInstallerPathKey); + var assemblyFileSpec = Path.Combine(Path.GetDirectoryName(installPath), $"{assemblyName}.dll"); + var assembly = Assembly.LoadFrom(assemblyFileSpec); + var type = assembly.GetType(strProgID); + Util.DebugWriteLine(this, ex.Message + $" So trying to get {strProgID} from {assemblyFileSpec} instead"); + rConverter = (IEncConverter) Activator.CreateInstance(type); + } + } + } if (rConverter == null) { Util.DebugWriteLine(this, "Returning null."); @@ -3157,11 +3158,11 @@ public bool AutoConfigure(ConvType eConversionTypeFilter, ref string strFriendly } catch (Exception e) { - var error = LogExceptionMessage("AutoConfigure", e); + var error = LogExceptionMessage("AutoConfigure", e); - MessageBox.Show($"AutoConfigure failed: {error}", traceSwitch.DisplayName); + MessageBox.Show($"AutoConfigure failed: {error}", traceSwitch.DisplayName); #if DEBUG - if (Util.IsUnix) + if (Util.IsUnix) { throw; } @@ -3171,20 +3172,20 @@ public bool AutoConfigure(ConvType eConversionTypeFilter, ref string strFriendly return false; } - public static string LogExceptionMessage(string className, Exception ex) - { - string msg = "Error occurred: " + ex.Message; - while (ex.InnerException != null) - { - ex = ex.InnerException; - msg += $"{Environment.NewLine}because: (InnerException): {ex.Message}"; - } + public static string LogExceptionMessage(string className, Exception ex) + { + string msg = "Error occurred: " + ex.Message; + while (ex.InnerException != null) + { + ex = ex.InnerException; + msg += $"{Environment.NewLine}because: (InnerException): {ex.Message}"; + } - Util.DebugWriteLine(className, msg); - return msg; - } + Util.DebugWriteLine(className, msg); + return msg; + } - public bool AutoConfigureEx + public bool AutoConfigureEx ( IEncConverter rIEncConverter, ConvType eConversionTypeFilter, @@ -4895,6 +4896,7 @@ public static void ThrowError(ErrStatus status, string strExtra) break; case ErrStatus.CompilationFailed: strRes = "IDS_kStatus_CompilationFailed"; + bFormatExtra = true; break; case ErrStatus.NameNotFound: strRes = "IDS_kStatus_NameNotFound"; @@ -5001,7 +5003,12 @@ public static void ThrowError(ErrStatus status, string strExtra) string strMsg = LocRM.GetString(strRes); if (bFormatExtra) - strMsg = String.Format(strMsg, strExtra); + { + if (strMsg.Contains("{0}")) + strMsg = String.Format(strMsg, strExtra); + else + strMsg = $"{strMsg}:{Environment.NewLine}{Environment.NewLine}{strExtra}"; + } ECException x = new ECException(strMsg, status); throw x; diff --git a/src/EncCnvtrs/TecEncConverter.cs b/src/EncCnvtrs/TecEncConverter.cs index 60696342..030e1d9d 100755 --- a/src/EncCnvtrs/TecEncConverter.cs +++ b/src/EncCnvtrs/TecEncConverter.cs @@ -458,7 +458,7 @@ static unsafe void DisplayCompilerError(byte* pszName, byte* msg, byte* param, U strCaption += "' converter"; if( MessageBox.Show(str, strCaption, MessageBoxButtons.OKCancel,MessageBoxIcon.Exclamation) == DialogResult.Cancel ) - EncConverters.ThrowError(ErrStatus.CompilationFailed); + EncConverters.ThrowError(ErrStatus.CompilationFailed, str); } protected unsafe void CompileMap(string strFilename, ref string strCompiledFilename) diff --git a/src/PyScriptEC/Py3ScriptAutoConfigDialog.Designer.cs b/src/PyScriptEC/Py3ScriptAutoConfigDialog.Designer.cs new file mode 100644 index 00000000..4fcd5107 --- /dev/null +++ b/src/PyScriptEC/Py3ScriptAutoConfigDialog.Designer.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SilEncConverters40 +{ + partial class Py3ScriptAutoConfigDialog + { + #region Windows Form Designer generated code + // This code does not get generated by Designer, so modify it directly. + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelScriptFile = new System.Windows.Forms.Label(); + this.textBoxFileSpec = new System.Windows.Forms.TextBox(); + this.buttonBrowse = new System.Windows.Forms.Button(); + this.labelPython3Path = new System.Windows.Forms.Label(); + this.textBoxPython3Path = new System.Windows.Forms.TextBox(); + this.buttonPython3Browse = new System.Windows.Forms.Button(); + this.openFileDialogBrowse = new System.Windows.Forms.OpenFileDialog(); + this.tabControl.SuspendLayout(); + this.tabPageSetup.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tabPageSetup + // + this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); + // + // buttonApply + // + this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonApply, true); + // + // buttonCancel + // + this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); + this.helpProvider.SetShowHelp(this.buttonCancel, true); + // + // buttonOK + // + this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonOK, true); + // + // buttonSaveInRepository + // + this.helpProvider.SetHelpString(this.buttonSaveInRepository, "Click to add this converter to the system repository permanently."); + this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 104F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.labelScriptFile, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxFileSpec, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.buttonBrowse, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.labelPython3Path, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.textBoxPython3Path, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.buttonPython3Browse, 2, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); + this.tableLayoutPanel1.TabIndex = 1; + // + // labelScriptFile + // + this.labelScriptFile.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelScriptFile.AutoSize = true; + this.labelScriptFile.Location = new System.Drawing.Point(14, 18); + this.labelScriptFile.Name = "labelScriptFile"; + this.labelScriptFile.Size = new System.Drawing.Size(87, 13); + this.labelScriptFile.TabIndex = 0; + this.labelScriptFile.Text = "Python script file:"; + // + // textBoxFileSpec + // + this.textBoxFileSpec.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.textBoxFileSpec.Location = new System.Drawing.Point(104, 15); + this.textBoxFileSpec.Margin = new System.Windows.Forms.Padding(0); + this.textBoxFileSpec.Name = "textBoxFileSpec"; + this.textBoxFileSpec.Size = new System.Drawing.Size(390, 20); + this.textBoxFileSpec.TabIndex = 1; + this.textBoxFileSpec.TextChanged += new System.EventHandler(this.textBoxFileSpec_TextChanged); + // + // buttonBrowse + // + this.buttonBrowse.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.buttonBrowse.AutoSize = true; + this.buttonBrowse.Location = new System.Drawing.Point(494, 13); + this.buttonBrowse.Margin = new System.Windows.Forms.Padding(0); + this.buttonBrowse.Name = "buttonBrowse"; + this.buttonBrowse.Size = new System.Drawing.Size(75, 23); + this.buttonBrowse.TabIndex = 2; + this.buttonBrowse.Text = "Browse..."; + this.buttonBrowse.Click += new System.EventHandler(this.buttonBrowse_Click); + // + // labelPython3Path + // + this.labelPython3Path.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelPython3Path.AutoSize = true; + this.labelPython3Path.Location = new System.Drawing.Point(5, 50); + this.labelPython3Path.Name = "labelPython3Path"; + this.labelPython3Path.Padding = new System.Windows.Forms.Padding(0, 5, 0, 0); + this.labelPython3Path.Size = new System.Drawing.Size(96, 18); + this.labelPython3Path.TabIndex = 5; + this.labelPython3Path.Text = "Python3 DLL path:"; + // + // textBoxPython3Path + // + this.textBoxPython3Path.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxPython3Path.Location = new System.Drawing.Point(107, 53); + this.textBoxPython3Path.Name = "textBoxPython3Path"; + this.textBoxPython3Path.Size = new System.Drawing.Size(384, 20); + this.textBoxPython3Path.TabIndex = 6; + // + // buttonPython3Browse + // + this.buttonPython3Browse.AutoSize = true; + this.buttonPython3Browse.Location = new System.Drawing.Point(494, 50); + this.buttonPython3Browse.Margin = new System.Windows.Forms.Padding(0); + this.buttonPython3Browse.Name = "buttonPython3Browse"; + this.buttonPython3Browse.Padding = new System.Windows.Forms.Padding(0, 2, 0, 0); + this.buttonPython3Browse.Size = new System.Drawing.Size(75, 25); + this.buttonPython3Browse.TabIndex = 2; + this.buttonPython3Browse.Text = "Browse..."; + this.buttonPython3Browse.Click += new System.EventHandler(this.buttonBrowseForPythonDll_Click); + // + // openFileDialogBrowse + // + this.openFileDialogBrowse.DefaultExt = "py"; + this.openFileDialogBrowse.Filter = "Python scrips (*.py)|*.py"; + this.openFileDialogBrowse.Title = "Browse for Python script"; + // + // Py3ScriptAutoConfigDialog + // + this.ClientSize = new System.Drawing.Size(634, 479); + this.Name = "Py3ScriptAutoConfigDialog"; + this.Controls.SetChildIndex(this.tabControl, 0); + this.Controls.SetChildIndex(this.buttonApply, 0); + this.Controls.SetChildIndex(this.buttonCancel, 0); + this.Controls.SetChildIndex(this.buttonOK, 0); + this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); + this.tabControl.ResumeLayout(false); + this.tabPageSetup.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label labelScriptFile; + private System.Windows.Forms.TextBox textBoxFileSpec; + private System.Windows.Forms.Button buttonBrowse; + private System.Windows.Forms.OpenFileDialog openFileDialogBrowse; + private Label labelPython3Path; + private TextBox textBoxPython3Path; + private Button buttonPython3Browse; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + } +} diff --git a/src/PyScriptEC/Py3ScriptAutoConfigDialog.cs b/src/PyScriptEC/Py3ScriptAutoConfigDialog.cs new file mode 100644 index 00000000..23c9f217 --- /dev/null +++ b/src/PyScriptEC/Py3ScriptAutoConfigDialog.cs @@ -0,0 +1,181 @@ +// Created by Bob Eaton on Oct 21 2023 +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.IO; +using ECInterfaces; // for IEncConverter + +namespace SilEncConverters40 +{ + public partial class Py3ScriptAutoConfigDialog : PythonAutoConfigDialog + { + public Py3ScriptAutoConfigDialog( + IEncConverters aECs, + string strDisplayName, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strLhsEncodingId, + string strRhsEncodingId, + int lProcessTypeFlags, + bool bIsInRepository) + { + Util.DebugWriteLine(this, "ctor1 BEGIN"); + InitializeComponent(); + Util.DebugWriteLine(this, "Initialized component."); + base.Initialize( + aECs, + Py3ScriptEncConverter.strHtmlFilename, + strDisplayName, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strLhsEncodingId, + strRhsEncodingId, + lProcessTypeFlags | (int)ProcessTypeFlags.PythonScript, + bIsInRepository); + Util.DebugWriteLine(this, "Initialized base."); + // if we're editing a CC table/spellfixer project, then set the + // Converter Spec and say it's unmodified + if (m_bEditMode) + { + Util.DebugWriteLine(this, "Edit mode"); + System.Diagnostics.Debug.Assert( + !String.IsNullOrEmpty(ConverterIdentifier)); + + textBoxFileSpec.Text = Py3ScriptEncConverter.ScriptPath(ConverterIdentifier); + textBoxPython3Path.Text = Py3ScriptEncConverter.DistroPath(ConverterIdentifier); + + IsModified = false; + } + m_bInitialized = true; + Util.DebugWriteLine(this, "END"); + } + + public Py3ScriptAutoConfigDialog( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData) + { + Util.DebugWriteLine(this, "ctor2 BEGIN"); + InitializeComponent(); + base.Initialize( + aECs, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strTestData); + Util.DebugWriteLine(this, "END"); + } + + // this method is called either when the user clicks the "Apply" or "OK" buttons *OR* if she + // tries to switch to the Test or Advanced tab. This is the dialog's one opportunity + // to make sure that the user has correctly configured a legitimate converter. + protected override bool OnApply() + { + Util.DebugWriteLine(this, "BEGIN"); + // Get the converter identifier from the Setup tab controls. + var scriptPath = textBoxFileSpec.Text; + var pythonDistroPath = textBoxPython3Path.Text; + + // if we're actually on the setup tab, then do some further checking as well. + if (tabControl.SelectedTab == tabPageSetup) + { + // only do these message boxes if we're on the Setup tab itself, because if this OnApply + // is being called as a result of the user switching to the Test tab, that code will + // already put up an error message and we don't need two error messages. + if (String.IsNullOrEmpty(scriptPath)) + { + MessageBox.Show(this, "Choose a Python script first!", EncConverters.cstrCaption); + return false; + } + else if (!File.Exists(scriptPath)) + { + MessageBox.Show(this, "File doesn't exist!", EncConverters.cstrCaption); + return false; + } + else if (String.IsNullOrEmpty(pythonDistroPath)) + { + MessageBox.Show(this, "You have to Browse to the path for the Python 3.* DLL file (e.g. Python312.dll)!", EncConverters.cstrCaption); + return false; + } + } + + ConverterIdentifier = $"{scriptPath};{pythonDistroPath}"; + + Util.DebugWriteLine(this, "END"); + return base.OnApply(); + } + + protected override string ProgID + { + get { return typeof(Py3ScriptEncConverter).FullName; } + } + + protected override string ImplType + { + get { return EncConverters.strTypeSILPy3Script; } + } + + protected override string DefaultFriendlyName + { + // as the default, make it the same as the table name (w/o extension) + get { return Path.GetFileNameWithoutExtension(Py3ScriptEncConverter.ScriptPath(ConverterIdentifier)); } + } + + private void buttonBrowse_Click(object sender, EventArgs e) + { + openFileDialogBrowse.DefaultExt = "py"; + openFileDialogBrowse.Filter = "Python scripts (*.py)|*.py"; + var scriptPath = Py3ScriptEncConverter.ScriptPath(ConverterIdentifier); + if (!String.IsNullOrEmpty(scriptPath)) + openFileDialogBrowse.InitialDirectory = Path.GetDirectoryName(scriptPath); + else + openFileDialogBrowse.InitialDirectory = Util.CommonAppDataPath() + EncConverters.strDefMapsTablesPath; + + if (openFileDialogBrowse.ShowDialog() == DialogResult.OK) + { + ResetFields(); + textBoxFileSpec.Text = openFileDialogBrowse.FileName; + } + } + + private void buttonBrowseForPythonDll_Click(object sender, EventArgs e) + { + openFileDialogBrowse.DefaultExt = "dll"; + openFileDialogBrowse.Filter = "Python 3 DLL (Python3 DLL)|Python3??.dll"; + var distroPath = Py3ScriptEncConverter.DistroPath(ConverterIdentifier); + if (!String.IsNullOrEmpty(distroPath)) + openFileDialogBrowse.InitialDirectory = Path.GetDirectoryName(distroPath); + else + openFileDialogBrowse.InitialDirectory = @"C:\"; + + if (openFileDialogBrowse.ShowDialog() == DialogResult.OK) + { + ResetFields(); + textBoxPython3Path.Text = openFileDialogBrowse.FileName; + } + } + + private void textBoxFileSpec_TextChanged(object sender, EventArgs e) + { + if (m_bInitialized) // but only do this after we're already initialized + { + IsModified = (((TextBox)sender).Text.Length > 0); + } + } + + private void radioButton_CheckedChanged(object sender, EventArgs e) + { + IsModified = true; + } + } +} + diff --git a/src/PyScriptEC/Py3ScriptAutoConfigDialog.resx b/src/PyScriptEC/Py3ScriptAutoConfigDialog.resx new file mode 100644 index 00000000..4cbbd5fe --- /dev/null +++ b/src/PyScriptEC/Py3ScriptAutoConfigDialog.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 341, 17 + + + 450, 17 + + \ No newline at end of file diff --git a/src/PyScriptEC/Py3ScriptEncConverter.cs b/src/PyScriptEC/Py3ScriptEncConverter.cs new file mode 100644 index 00000000..3f3cde55 --- /dev/null +++ b/src/PyScriptEC/Py3ScriptEncConverter.cs @@ -0,0 +1,307 @@ +// Created by Jim Kornelsen on Nov 14 2011 +// +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.Win32; // for RegistryKey +using ECInterfaces; // for IEncConverter +using Python.Runtime; +using System.Windows.Forms; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; + +namespace SilEncConverters40 +{ + /// + /// Managed Python script EncConverter for Python 3 + /// + //[GuidAttribute("54E0185D-3603-4113-B323-E0222FAD4CCE")] + // normally these subclasses are treated as the base class (i.e. the + // client can use them orthogonally as IEncConverter interface pointers + // so normally these individual subclasses would be invisible), but if + // we add 'ComVisible = false', then it doesn't get the registry + // 'HKEY_CLASSES_ROOT\SilEncConverters40.TecEncConverter' which is the basis of + // how it is started (see EncConverters.AddEx). + // [ComVisible(false)] + public class Py3ScriptEncConverter : EncConverter + { + #region Member Variable Definitions + private DateTime m_timeModified = DateTime.MinValue; + protected bool m_bLegacy; + + public const string strDisplayName = "Python 3 Script"; + public const string strHtmlFilename = "Python_3_Script_Plug-in_About_box.htm"; + #endregion Member Variable Definitions + + #region Initialization + /// + /// The class constructor. + public Py3ScriptEncConverter() : base( + typeof(Py3ScriptEncConverter).FullName, EncConverters.strTypeSILPy3Script) + { + } + + ~Py3ScriptEncConverter() + { + moduleImported?.Dispose(); + //if (PythonEngine.IsInitialized) + // PythonEngine.Shutdown(); + } + + public override void Initialize( + string converterName, + string converterSpec, + ref string lhsEncodingID, + ref string rhsEncodingID, + ref ConvType conversionType, + ref Int32 processTypeFlags, + Int32 codePageInput, + Int32 codePageOutput, + bool bAdding) + { + Util.DebugWriteLine(this, "BEGIN"); + // let the base class have first stab at it + base.Initialize(converterName, converterSpec, ref lhsEncodingID, ref rhsEncodingID, + ref conversionType, ref processTypeFlags, codePageInput, codePageOutput, bAdding); + + // the only thing we want to add (now that the convType can be less than accurate) + // is to make sure it's unidirectional + m_eConversionType = conversionType = MakeUniDirectional(conversionType); + m_bLegacy = (EncConverter.NormalizeLhsConversionType(conversionType) == NormConversionType.eLegacy); + + // if we're supposedly adding this one, then clobber our copy of its last modified + // (there was a problem with us instantiating lots of these things in a row and + // not detecting the change because the modified date was within a second of each + // other) + if (bAdding) + { + Util.DebugWriteLine(this, "Adding"); + m_timeModified = DateTime.MinValue; + + // do the load at this point; not that we need it, but for checking that everything's okay. + Load(); + } + Util.DebugWriteLine(this, "END"); + } + + #endregion Initialization + + #region Abstract Base Class Overrides + protected override void PreConvert + ( + EncodingForm eInEncodingForm, + ref EncodingForm eInFormEngine, + EncodingForm eOutEncodingForm, + ref EncodingForm eOutFormEngine, + ref NormalizeFlags eNormalizeOutput, + bool bForward + ) + { + // let the base class do its thing first + base.PreConvert(eInEncodingForm, ref eInFormEngine, + eOutEncodingForm, ref eOutFormEngine, + ref eNormalizeOutput, bForward); + + if (NormalizeLhsConversionType(ConversionType) == NormConversionType.eUnicode) + { + // We could use UTF-8 here, but wide data works just fine. + // the Windows version definitely needs UTF16. + if (Util.IsUnix) + { + Util.DebugWriteLine(this, "eInFormEngine UTF32"); + eInFormEngine = EncodingForm.UTF32; + } + else + { + Util.DebugWriteLine(this, "eInFormEngine UTF16"); + eInFormEngine = EncodingForm.UTF16; + } + } + else + { + // legacy + Util.DebugWriteLine(this, "eInFormEngine LegacyBytes"); + eInFormEngine = EncodingForm.LegacyBytes; + } + + if (NormalizeRhsConversionType(ConversionType) == NormConversionType.eUnicode) + { + if (Util.IsUnix) + { + Util.DebugWriteLine(this, "eOutFormEngine UTF32"); + eOutFormEngine = EncodingForm.UTF32; + } + else + { + Util.DebugWriteLine(this, "eOutFormEngine UTF16"); + eOutFormEngine = EncodingForm.UTF16; + } + } + else + { + Util.DebugWriteLine(this, "eOutFormEngine LegacyBytes"); + eOutFormEngine = EncodingForm.LegacyBytes; + } + + // do the load at this point + Load(); + } + + public static string ScriptPath(string converterIdentifier) + { + return converterIdentifier?.Split(';')?[0]; + } + + public static string DistroPath(string converterIdentifier) + { + return (converterIdentifier?.Contains(";") ?? false) ? converterIdentifier?.Split(';')?[1] : null; + } + + protected unsafe void Load() + { + Util.DebugWriteLine(this, "BEGIN"); + string strScriptPath = ScriptPath(ConverterIdentifier); + + // first make sure it's there and get the last time it was modified + DateTime timeModified = DateTime.Now; // don't care really, but have to initialize it. + if (!DoesFileExist(strScriptPath, ref timeModified)) + EncConverters.ThrowError(ErrStatus.CantOpenReadMap, strScriptPath); + + // if it has been modified or it's not already loaded... + if (timeModified > m_timeModified) + { + // keep track of the modified date, so we can detect a new version to reload + m_timeModified = timeModified; + + Util.DebugWriteLine(this, "Calling CppInitialize"); + string strScriptName = Path.GetFileNameWithoutExtension(strScriptPath); + string strScriptDir = Path.GetDirectoryName(strScriptPath); + var strErrorExtraValue = strScriptPath; + try + { + var distroPath = DistroPath(ConverterIdentifier); + if (Runtime.PythonDLL != distroPath) + Runtime.PythonDLL = distroPath; + + if (!PythonEngine.IsInitialized) + { + PythonEngine.Initialize(); + } + + // causes access violation and may not be needed (since this isn't async): + // PythonEngine.BeginAllowThreads(); + dynamic sysModule = Py.Import("sys"); + strScriptDir = strScriptDir.Replace(@"\", "/"); + sysModule.path.append(strScriptDir); + + using (Py.GIL()) + { + moduleImported = Py.Import(strScriptName); + } + } + catch (Exception ex) + { + strErrorExtraValue = LogExceptionMessage("Py3ScriptEncConverter.Load", ex); + } + finally + { + if (moduleImported == null) + { + EncConverters.ThrowError(ErrStatus.CompilationFailed, strErrorExtraValue); + } + } + Util.DebugWriteLine(this, "Finished calling CppInitialize"); + } + Util.DebugWriteLine(this, "END"); + } + + protected dynamic moduleImported; + + protected override unsafe void DoConvert + ( + byte* lpInBuffer, + int nInLen, + byte* lpOutBuffer, + ref int rnOutLen + ) + { + int status = 0; + fixed (int* pnOut = &rnOutLen) + { + byte[] baIn = new byte[nInLen]; + ECNormalizeData.ByteStarToByteArr(lpInBuffer, nInLen, baIn); +#if DEBUG + if (Util.IsUnix) + { + Util.DebugWriteLine(this, Util.getDisplayBytes("Sending bytes to CppDoConvert", baIn)); + } +#endif + + Encoding enc; + if (m_bLegacy) + { + try + { + enc = Encoding.GetEncoding(this.CodePageInput); + } + catch + { + enc = Encoding.GetEncoding(EncConverters.cnIso8859_1CodePage); + } + } + else + { + enc = Encoding.Unicode; + } + + char[] caIn = Encoding.Unicode.GetChars(baIn); + + // here's our input string + var strInput = new string(caIn); + + // status = CppDoConvert(lpInBuffer, nInLen, lpOutBuffer, pnOut); + using (Py.GIL()) + { + string strOutput = moduleImported?.Convert(strInput); + StringToProperByteStar(strOutput, lpOutBuffer, ref rnOutLen); + Util.DebugWriteLine(this, "Result len " + rnOutLen.ToString()); + Util.DebugWriteLine(this, "END"); + } + } + + if (status != 0) + { + EncConverters.ThrowError(status); + } + } + + protected override string GetConfigTypeName + { + get { return typeof(Py3ScriptEncConverterConfig).AssemblyQualifiedName; } + } + + internal static unsafe void StringToProperByteStar(string strOutput, byte* lpOutBuffer, ref int rnOutLen) + { + int nLen = strOutput.Length * 2; + if (nLen > (int)rnOutLen) + EncConverters.ThrowError(ErrStatus.OutputBufferFull); + rnOutLen = nLen; + ECNormalizeData.StringToByteStar(strOutput, lpOutBuffer, rnOutLen, false); + } + + internal static string LogExceptionMessage(string className, Exception ex) + { + string msg = "Error occurred: " + ex.Message; + while (ex.InnerException != null) + { + ex = ex.InnerException; + msg += $"{Environment.NewLine}because: (InnerException): {ex.Message}"; + } + + Util.DebugWriteLine(className, msg); + return msg; + } + + #endregion Abstract Base Class Overrides + } +} diff --git a/src/PyScriptEC/Py3ScriptEncConverterConfig.cs b/src/PyScriptEC/Py3ScriptEncConverterConfig.cs new file mode 100644 index 00000000..08b2b3fe --- /dev/null +++ b/src/PyScriptEC/Py3ScriptEncConverterConfig.cs @@ -0,0 +1,61 @@ +// Created by Jim Kornelsen on Nov 14 2011 +// +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; // for the class attributes +using ECInterfaces; // for IEncConverter + +namespace SilEncConverters40 +{ + public class Py3ScriptEncConverterConfig : EncConverterConfig + { + public Py3ScriptEncConverterConfig() + : base + ( + typeof(Py3ScriptEncConverter).FullName, + Py3ScriptEncConverter.strDisplayName, + Py3ScriptEncConverter.strHtmlFilename, + ProcessTypeFlags.DontKnow + ) + { + } + + public override bool Configure + ( + IEncConverters aECs, + string strFriendlyName, + ConvType eConversionType, + string strLhsEncodingID, + string strRhsEncodingID + ) + { + var form = new Py3ScriptAutoConfigDialog ( + aECs, m_strDisplayName, m_strFriendlyName, + m_strConverterID, m_eConversionType, + BestGuessEncoding(m_strLhsEncodingID, strLhsEncodingID, EncConverters.strDefUnicodeEncoding), + BestGuessEncoding(m_strRhsEncodingID, strRhsEncodingID, EncConverters.strDefUnicodeEncoding), + m_lProcessType, m_bIsInRepository); + + return Configure(form); + } + + public override void DisplayTestPage + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + InitializeFromThis(ref strFriendlyName, ref strConverterIdentifier, + ref eConversionType, ref strTestData); + + Py3ScriptAutoConfigDialog form = new Py3ScriptAutoConfigDialog(aECs, strFriendlyName, + strConverterIdentifier, eConversionType, strTestData); + + base.DisplayTestPage(form); + } + } +} diff --git a/src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs b/src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs index 563d85df..6fa74efc 100644 --- a/src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs +++ b/src/PyScriptEC/PyScriptAutoConfigDialog.Designer.cs @@ -7,225 +7,224 @@ namespace SilEncConverters40 { - partial class PyScriptAutoConfigDialog - { - #region Windows Form Designer generated code - // This code does not get generated by Designer, so modify it directly. - private void InitializeComponent() - { - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.labelScriptFile = new System.Windows.Forms.Label(); - this.textBoxFileSpec = new System.Windows.Forms.TextBox(); - this.buttonBrowse = new System.Windows.Forms.Button(); - this.groupBoxExpects = new System.Windows.Forms.GroupBox(); - this.radioButtonExpectsUnicode = new System.Windows.Forms.RadioButton(); - this.radioButtonExpectsLegacy = new System.Windows.Forms.RadioButton(); - this.groupBoxReturns = new System.Windows.Forms.GroupBox(); - this.radioButtonReturnsUnicode = new System.Windows.Forms.RadioButton(); - this.radioButtonReturnsLegacy = new System.Windows.Forms.RadioButton(); - this.openFileDialogBrowse = new System.Windows.Forms.OpenFileDialog(); - this.tabControl.SuspendLayout(); - this.tabPageSetup.SuspendLayout(); - this.tableLayoutPanel1.SuspendLayout(); - this.groupBoxExpects.SuspendLayout(); - this.groupBoxReturns.SuspendLayout(); - this.SuspendLayout(); - // - // tabPageSetup - // - this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); - // - // buttonApply - // - this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); - this.helpProvider.SetShowHelp(this.buttonApply, true); - // - // buttonCancel - // - this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); - this.helpProvider.SetShowHelp(this.buttonCancel, true); - // - // buttonOK - // - this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); - this.helpProvider.SetShowHelp(this.buttonOK, true); - // - // buttonSaveInRepository - // - this.helpProvider.SetHelpString(this.buttonSaveInRepository, "Click to add this converter to the system repository permanently."); - this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 3; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 104F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.Controls.Add(this.labelScriptFile, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.textBoxFileSpec, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.buttonBrowse, 2, 0); - this.tableLayoutPanel1.Controls.Add(this.groupBoxExpects, 1, 2); - this.tableLayoutPanel1.Controls.Add(this.groupBoxReturns, 1, 3); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 5; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); - this.tableLayoutPanel1.TabIndex = 1; - // - // labelScriptFile - // - this.labelScriptFile.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.labelScriptFile.AutoSize = true; - this.labelScriptFile.Location = new System.Drawing.Point(14, 18); - this.labelScriptFile.Name = "labelScriptFile"; - this.labelScriptFile.Size = new System.Drawing.Size(87, 13); - this.labelScriptFile.TabIndex = 0; - this.labelScriptFile.Text = "Python script file:"; - // - // textBoxFileSpec - // - this.textBoxFileSpec.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.textBoxFileSpec.Location = new System.Drawing.Point(104, 15); - this.textBoxFileSpec.Margin = new System.Windows.Forms.Padding(0); - this.textBoxFileSpec.Name = "textBoxFileSpec"; - this.textBoxFileSpec.Size = new System.Drawing.Size(390, 20); - this.textBoxFileSpec.TabIndex = 1; - this.textBoxFileSpec.TextChanged += new System.EventHandler(this.textBoxFileSpec_TextChanged); - // - // buttonBrowse - // - this.buttonBrowse.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.buttonBrowse.AutoSize = true; - this.buttonBrowse.Location = new System.Drawing.Point(494, 13); - this.buttonBrowse.Margin = new System.Windows.Forms.Padding(0); - this.buttonBrowse.Name = "buttonBrowse"; - this.buttonBrowse.Size = new System.Drawing.Size(75, 23); - this.buttonBrowse.TabIndex = 2; - this.buttonBrowse.Text = "Browse..."; - this.buttonBrowse.Click += new System.EventHandler(this.buttonBrowse_Click); - // - // groupBoxExpects - // - this.groupBoxExpects.Controls.Add(this.radioButtonExpectsUnicode); - this.groupBoxExpects.Controls.Add(this.radioButtonExpectsLegacy); - this.groupBoxExpects.Dock = System.Windows.Forms.DockStyle.Fill; - this.groupBoxExpects.Location = new System.Drawing.Point(107, 136); - this.groupBoxExpects.Name = "groupBoxExpects"; - this.groupBoxExpects.Size = new System.Drawing.Size(384, 77); - this.groupBoxExpects.TabIndex = 3; - this.groupBoxExpects.TabStop = false; - this.groupBoxExpects.Text = "Python function expects"; - this.groupBoxExpects.Visible = false; - // - // radioButtonExpectsUnicode - // - this.radioButtonExpectsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonExpectsUnicode.AutoSize = true; - this.radioButtonExpectsUnicode.Location = new System.Drawing.Point(50, 30); - this.radioButtonExpectsUnicode.Name = "radioButtonExpectsUnicode"; - this.radioButtonExpectsUnicode.Size = new System.Drawing.Size(95, 17); - this.radioButtonExpectsUnicode.TabIndex = 0; - this.radioButtonExpectsUnicode.TabStop = true; - this.radioButtonExpectsUnicode.Text = "Unicode String"; - this.radioButtonExpectsUnicode.UseVisualStyleBackColor = true; - this.radioButtonExpectsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - // - // radioButtonExpectsLegacy - // - this.radioButtonExpectsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonExpectsLegacy.AutoSize = true; - this.radioButtonExpectsLegacy.Location = new System.Drawing.Point(200, 30); - this.radioButtonExpectsLegacy.Name = "radioButtonExpectsLegacy"; - this.radioButtonExpectsLegacy.Size = new System.Drawing.Size(117, 17); - this.radioButtonExpectsLegacy.TabIndex = 0; - this.radioButtonExpectsLegacy.TabStop = true; - this.radioButtonExpectsLegacy.Text = "Non-Unicode Bytes"; - this.radioButtonExpectsLegacy.UseVisualStyleBackColor = true; - this.radioButtonExpectsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - // - // groupBoxReturns - // - this.groupBoxReturns.Controls.Add(this.radioButtonReturnsUnicode); - this.groupBoxReturns.Controls.Add(this.radioButtonReturnsLegacy); - this.groupBoxReturns.Dock = System.Windows.Forms.DockStyle.Fill; - this.groupBoxReturns.Location = new System.Drawing.Point(107, 219); - this.groupBoxReturns.Name = "groupBoxReturns"; - this.groupBoxReturns.Size = new System.Drawing.Size(384, 77); - this.groupBoxReturns.TabIndex = 4; - this.groupBoxReturns.TabStop = false; - this.groupBoxReturns.Text = "Python function returns"; - this.groupBoxReturns.Visible = false; - // - // radioButtonReturnsUnicode - // - this.radioButtonReturnsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonReturnsUnicode.AutoSize = true; - this.radioButtonReturnsUnicode.Location = new System.Drawing.Point(50, 30); - this.radioButtonReturnsUnicode.Name = "radioButtonReturnsUnicode"; - this.radioButtonReturnsUnicode.Size = new System.Drawing.Size(95, 17); - this.radioButtonReturnsUnicode.TabIndex = 0; - this.radioButtonReturnsUnicode.TabStop = true; - this.radioButtonReturnsUnicode.Text = "Unicode String"; - this.radioButtonReturnsUnicode.UseVisualStyleBackColor = true; - this.radioButtonReturnsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - // - // radioButtonReturnsLegacy - // - this.radioButtonReturnsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; - this.radioButtonReturnsLegacy.AutoSize = true; - this.radioButtonReturnsLegacy.Location = new System.Drawing.Point(200, 30); - this.radioButtonReturnsLegacy.Name = "radioButtonReturnsLegacy"; - this.radioButtonReturnsLegacy.Size = new System.Drawing.Size(118, 17); - this.radioButtonReturnsLegacy.TabIndex = 0; - this.radioButtonReturnsLegacy.TabStop = true; - this.radioButtonReturnsLegacy.Text = "Non-Unicode String"; - this.radioButtonReturnsLegacy.UseVisualStyleBackColor = true; - this.radioButtonReturnsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); - // - // openFileDialogBrowse - // - this.openFileDialogBrowse.DefaultExt = "py"; - this.openFileDialogBrowse.Filter = "Python scrips (*.py)|*.py"; - this.openFileDialogBrowse.Title = "Browse for Python script"; - // - // PyScriptAutoConfigDialog - // - this.ClientSize = new System.Drawing.Size(634, 479); - this.Name = "PyScriptAutoConfigDialog"; - this.Controls.SetChildIndex(this.tabControl, 0); - this.Controls.SetChildIndex(this.buttonApply, 0); - this.Controls.SetChildIndex(this.buttonCancel, 0); - this.Controls.SetChildIndex(this.buttonOK, 0); - this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); - this.tabControl.ResumeLayout(false); - this.tabPageSetup.ResumeLayout(false); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - this.groupBoxExpects.ResumeLayout(false); - this.groupBoxExpects.PerformLayout(); - this.groupBoxReturns.ResumeLayout(false); - this.groupBoxReturns.PerformLayout(); - this.ResumeLayout(false); - } + partial class PyScriptAutoConfigDialog + { + #region Windows Form Designer generated code + // This code does not get generated by Designer, so modify it directly. + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelScriptFile = new System.Windows.Forms.Label(); + this.textBoxFileSpec = new System.Windows.Forms.TextBox(); + this.buttonBrowse = new System.Windows.Forms.Button(); + this.groupBoxExpects = new System.Windows.Forms.GroupBox(); + this.radioButtonExpectsUnicode = new System.Windows.Forms.RadioButton(); + this.radioButtonExpectsLegacy = new System.Windows.Forms.RadioButton(); + this.groupBoxReturns = new System.Windows.Forms.GroupBox(); + this.radioButtonReturnsUnicode = new System.Windows.Forms.RadioButton(); + this.radioButtonReturnsLegacy = new System.Windows.Forms.RadioButton(); + this.openFileDialogBrowse = new System.Windows.Forms.OpenFileDialog(); + this.tabControl.SuspendLayout(); + this.tabPageSetup.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.groupBoxExpects.SuspendLayout(); + this.groupBoxReturns.SuspendLayout(); + this.SuspendLayout(); + // + // tabPageSetup + // + this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); + // + // buttonApply + // + this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonApply, true); + // + // buttonCancel + // + this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); + this.helpProvider.SetShowHelp(this.buttonCancel, true); + // + // buttonOK + // + this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonOK, true); + // + // buttonSaveInRepository + // + this.helpProvider.SetHelpString(this.buttonSaveInRepository, "Click to add this converter to the system repository permanently."); + this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 104F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.labelScriptFile, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxFileSpec, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.buttonBrowse, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.groupBoxExpects, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.groupBoxReturns, 1, 3); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); + this.tableLayoutPanel1.TabIndex = 1; + // + // labelScriptFile + // + this.labelScriptFile.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelScriptFile.AutoSize = true; + this.labelScriptFile.Location = new System.Drawing.Point(14, 18); + this.labelScriptFile.Name = "labelScriptFile"; + this.labelScriptFile.Size = new System.Drawing.Size(87, 13); + this.labelScriptFile.TabIndex = 0; + this.labelScriptFile.Text = "Python script file:"; + // + // textBoxFileSpec + // + this.textBoxFileSpec.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.textBoxFileSpec.Location = new System.Drawing.Point(104, 15); + this.textBoxFileSpec.Margin = new System.Windows.Forms.Padding(0); + this.textBoxFileSpec.Name = "textBoxFileSpec"; + this.textBoxFileSpec.Size = new System.Drawing.Size(390, 20); + this.textBoxFileSpec.TabIndex = 1; + this.textBoxFileSpec.TextChanged += new System.EventHandler(this.textBoxFileSpec_TextChanged); + // + // buttonBrowse + // + this.buttonBrowse.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.buttonBrowse.AutoSize = true; + this.buttonBrowse.Location = new System.Drawing.Point(494, 13); + this.buttonBrowse.Margin = new System.Windows.Forms.Padding(0); + this.buttonBrowse.Name = "buttonBrowse"; + this.buttonBrowse.Size = new System.Drawing.Size(75, 23); + this.buttonBrowse.TabIndex = 2; + this.buttonBrowse.Text = "Browse..."; + this.buttonBrowse.Click += new System.EventHandler(this.buttonBrowse_Click); + // + // groupBoxExpects + // + this.groupBoxExpects.Controls.Add(this.radioButtonExpectsUnicode); + this.groupBoxExpects.Controls.Add(this.radioButtonExpectsLegacy); + this.groupBoxExpects.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxExpects.Location = new System.Drawing.Point(107, 53); + this.groupBoxExpects.Name = "groupBoxExpects"; + this.groupBoxExpects.Size = new System.Drawing.Size(384, 77); + this.groupBoxExpects.TabIndex = 3; + this.groupBoxExpects.TabStop = false; + this.groupBoxExpects.Text = "Python function expects"; + // + // radioButtonExpectsUnicode + // + this.radioButtonExpectsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonExpectsUnicode.AutoSize = true; + this.radioButtonExpectsUnicode.Location = new System.Drawing.Point(50, 30); + this.radioButtonExpectsUnicode.Name = "radioButtonExpectsUnicode"; + this.radioButtonExpectsUnicode.Size = new System.Drawing.Size(95, 17); + this.radioButtonExpectsUnicode.TabIndex = 0; + this.radioButtonExpectsUnicode.TabStop = true; + this.radioButtonExpectsUnicode.Text = "Unicode String"; + this.radioButtonExpectsUnicode.UseVisualStyleBackColor = true; + this.radioButtonExpectsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // radioButtonExpectsLegacy + // + this.radioButtonExpectsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonExpectsLegacy.AutoSize = true; + this.radioButtonExpectsLegacy.Location = new System.Drawing.Point(200, 30); + this.radioButtonExpectsLegacy.Name = "radioButtonExpectsLegacy"; + this.radioButtonExpectsLegacy.Size = new System.Drawing.Size(117, 17); + this.radioButtonExpectsLegacy.TabIndex = 0; + this.radioButtonExpectsLegacy.TabStop = true; + this.radioButtonExpectsLegacy.Text = "Non-Unicode Bytes"; + this.radioButtonExpectsLegacy.UseVisualStyleBackColor = true; + this.radioButtonExpectsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // groupBoxReturns + // + this.groupBoxReturns.Controls.Add(this.radioButtonReturnsUnicode); + this.groupBoxReturns.Controls.Add(this.radioButtonReturnsLegacy); + this.groupBoxReturns.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxReturns.Location = new System.Drawing.Point(107, 136); + this.groupBoxReturns.Name = "groupBoxReturns"; + this.groupBoxReturns.Size = new System.Drawing.Size(384, 77); + this.groupBoxReturns.TabIndex = 4; + this.groupBoxReturns.TabStop = false; + this.groupBoxReturns.Text = "Python function returns"; + // + // radioButtonReturnsUnicode + // + this.radioButtonReturnsUnicode.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonReturnsUnicode.AutoSize = true; + this.radioButtonReturnsUnicode.Location = new System.Drawing.Point(50, 30); + this.radioButtonReturnsUnicode.Name = "radioButtonReturnsUnicode"; + this.radioButtonReturnsUnicode.Size = new System.Drawing.Size(95, 17); + this.radioButtonReturnsUnicode.TabIndex = 0; + this.radioButtonReturnsUnicode.TabStop = true; + this.radioButtonReturnsUnicode.Text = "Unicode String"; + this.radioButtonReturnsUnicode.UseVisualStyleBackColor = true; + this.radioButtonReturnsUnicode.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // radioButtonReturnsLegacy + // + this.radioButtonReturnsLegacy.Anchor = System.Windows.Forms.AnchorStyles.None; + this.radioButtonReturnsLegacy.AutoSize = true; + this.radioButtonReturnsLegacy.Location = new System.Drawing.Point(200, 30); + this.radioButtonReturnsLegacy.Name = "radioButtonReturnsLegacy"; + this.radioButtonReturnsLegacy.Size = new System.Drawing.Size(118, 17); + this.radioButtonReturnsLegacy.TabIndex = 0; + this.radioButtonReturnsLegacy.TabStop = true; + this.radioButtonReturnsLegacy.Text = "Non-Unicode String"; + this.radioButtonReturnsLegacy.UseVisualStyleBackColor = true; + this.radioButtonReturnsLegacy.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // openFileDialogBrowse + // + this.openFileDialogBrowse.DefaultExt = "py"; + this.openFileDialogBrowse.Filter = "Python scrips (*.py)|*.py"; + this.openFileDialogBrowse.Title = "Browse for Python script"; + // + // PyScriptAutoConfigDialog + // + this.ClientSize = new System.Drawing.Size(634, 479); + this.Name = "PyScriptAutoConfigDialog"; + this.Controls.SetChildIndex(this.tabControl, 0); + this.Controls.SetChildIndex(this.buttonApply, 0); + this.Controls.SetChildIndex(this.buttonCancel, 0); + this.Controls.SetChildIndex(this.buttonOK, 0); + this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); + this.tabControl.ResumeLayout(false); + this.tabPageSetup.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.groupBoxExpects.ResumeLayout(false); + this.groupBoxExpects.PerformLayout(); + this.groupBoxReturns.ResumeLayout(false); + this.groupBoxReturns.PerformLayout(); + this.ResumeLayout(false); - #endregion + } - private System.Windows.Forms.Label labelScriptFile; - private System.Windows.Forms.TextBox textBoxFileSpec; - private System.Windows.Forms.Button buttonBrowse; - private System.Windows.Forms.OpenFileDialog openFileDialogBrowse; - private System.Windows.Forms.GroupBox groupBoxExpects; - private System.Windows.Forms.RadioButton radioButtonExpectsUnicode; - private System.Windows.Forms.RadioButton radioButtonExpectsLegacy; - private System.Windows.Forms.GroupBox groupBoxReturns; - private System.Windows.Forms.RadioButton radioButtonReturnsLegacy; - private System.Windows.Forms.RadioButton radioButtonReturnsUnicode; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - } + #endregion + + private System.Windows.Forms.Label labelScriptFile; + private System.Windows.Forms.TextBox textBoxFileSpec; + private System.Windows.Forms.Button buttonBrowse; + private System.Windows.Forms.OpenFileDialog openFileDialogBrowse; + private System.Windows.Forms.GroupBox groupBoxExpects; + private System.Windows.Forms.RadioButton radioButtonExpectsUnicode; + private System.Windows.Forms.RadioButton radioButtonExpectsLegacy; + private System.Windows.Forms.GroupBox groupBoxReturns; + private System.Windows.Forms.RadioButton radioButtonReturnsLegacy; + private System.Windows.Forms.RadioButton radioButtonReturnsUnicode; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + } } diff --git a/src/PyScriptEC/PyScriptEC 2010.csproj b/src/PyScriptEC/PyScriptEC 2010.csproj index 73408f06..6aa8740d 100644 --- a/src/PyScriptEC/PyScriptEC 2010.csproj +++ b/src/PyScriptEC/PyScriptEC 2010.csproj @@ -1,4 +1,4 @@ - + Debug @@ -83,6 +83,10 @@ AllRules.ruleset + + + ..\..\packages\pythonnet.3.0.3\lib\netstandard2.0\Python.Runtime.dll + 3.5 @@ -100,13 +104,21 @@ + + Form + + + Py3ScriptAutoConfigDialog.cs + Form + PyScriptAutoConfigDialog.cs + Form @@ -140,12 +152,17 @@ + + Py3ScriptAutoConfigDialog.cs + PyScriptAutoConfigDialog.cs + Designer + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs b/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs index 05cecf46..a679aca9 100644 --- a/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs +++ b/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs @@ -9,90 +9,143 @@ - + - + - + - - + + + + + + + + - + - + - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -110,7 +163,13 @@ - + + + + + + + @@ -126,7 +185,7 @@ Source="..\..\output\Win32\release\BackTranslationHelper.dll"/> - + @@ -423,7 +482,31 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml b/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml index 79d029fb..42766727 100644 --- a/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml +++ b/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml @@ -18,6 +18,12 @@ DisplayName="Google Translate" ConfiguratorProgId="SilEncConverters40.EcTranslators.GoogleTranslator.GoogleTranslatorEncConverterConfig" AssemblyReference="EcTranslators, Version=4.0.0.0, Culture=neutral, PublicKeyToken=f1447bae1e63f485" /> + + + + + + + + + + + +NLLB Translator + + + + + + + + + + + +
+ +

No Language Left +Behind (NLLB) Translator

+ +

This +converter allows you to use the Meta +No Language Left Behind (NLLB) Translator to perform text processing within +EncConverter-enabled applications. The NLLB Translator is currently a +local translation service, but is expected to be +online as well with a larger data model by the end of 2023. It can be used to +perform language translation between a growing number of languages (see here for specific supported languages).

+ +

The +NLLB Translator, which is available in EncConverter-enabled applications, +currently requires a number of complex additional +steps to use beyond simply installing the EncConverter. You may need to update Powershell on your computer, and then download and install Docker (e.g. Docker Desktop for Windows), pull a github repository, +run some commands in Powershell to build the Docker container, which +downloads the NLLB model and other prerequisites (~2.5 GB), and creates an +interface to the model. Finally, you need to run the Docker container to allow +the NLLB Translator EncConverter to access the model. These complex +prerequisites are discussed below.

+ +

Virtualization +Check

+ +

To download and use Docker, your computer must support +virtualization. To check if your computer supports virtualization, press the Ctrl ++ Shift + Esc keys to open the Task Manager dialog. On the Performance tab, look for Virtualization line in the CPU section to see +if it’s Enabled:

+ +

+ +

Figure 1: +Virtualization Check

+ +

If it’s not enabled, you may be able to enable it in +your BIOS settings (if your computer supports it). But if it doesn’t +support virtualization, then you won’t be able to use this +Translator/EncConverter.

+ +

Update Powershell

+ +

Most Windows computers already have Powershell installed on +them, and by default, you can open Powershell and run this command to update +Powershell:

+ +

winget install --id Microsoft.Powershell --source winget

+ +

If this doesn’t work, then you can install the +latest version of Powershell by following the instructions on this page.

+ +

Install Docker

+ +

Download a Windows (or other OS) installer for Docker from +here +and install it.

+ +

The latest installer will show a window like this:

+ +

+ +

Figure 2: Docker Installer

+ +

Keep these settings checked and click the Ok button.

+ +

After the installation is complete, you will need to +restart your computer. Then open Docker for +Desktop and accept the agreement to complete the installation using the +recommended settings (requires administrator password).

+ +

Once this is complete, you can either sign up or sign in or you can just Continue +without signing in.

+ +

Download Github +Repository

+ +

To download the required github repository, you must have git installed on your computer. To see if you have +git installed, you can execute this command in your Powershell window:

+ +

git --version

+ +

If you get a message saying that the term ‘git’ +is not recognized, then you will need to install git on your computer first. +You can find an installer for Windows from this +site. There are a lot of questions in the gitforwindows installer, but if you +just accept the defaults, it will work for what you need to do for this +process. You will need to restart you Powershell +window.

+ +

Once you have git installed, to pull the necessary github +repository, execute this command in your Powershell window, where you change C:\path\to\desired\directory to +the folder path where you want the repository to go into (e.g. +D:\repos\NNLB):

+ +

git clone https://github.com/Nateowami/NLLB-demo.git +C:\path\to\desired\directory

+ +

If it looks like it failed for some reason, double-check +that you don’t have the repository downloaded in the location you +requested. If it really did fail, then you might need to upgrade git, for which +you can try this command:

+ +

git +update-git-for-windows

+ +

Build Docker +Container

+ +

The next step is to run some Powershell commands in the +folder where the github repository was installed. Suppose the repository was +installed to the D:\repos\NNLB +folder. In your Powershell window, change to that folder with the command:

+ +

cd D:\repos\NLLB

+ +

and then make sure that Docker +for Desktop is running and execute this command in the Powershell window +(note the space and period (.) at the end):

+ +

docker build -t nllb .

+ +

This step can take a long time, because +it must download the NLLB model and several other prerequisites (~2.5 GB).

+ +

Run Docker +Container

+ +

The final step to prepare the NLLB model is to execute the +following command in Powershell after the docker build step completes:

+ +

docker run -p 8000:8000 nllb

+ +

To see if everything is working properly, you can open the +url, localhost:8000, in a web +browser, and you should see the following in your browser:

+ +

+ +

Figure 3: NLLB Demo webpage (at localhost:8000)

+ +

Choose the Input language +and Output language you want to test and +click the Translate button to verify the service is working.

+ +

Once this is complete, then you are ready to connect the +NLLB Translator EncConverter to this service.

+ +

Setup Tab

+ +

To bring up the Setup dialog for the NLLB Translator, you +can run, for example, the Clipboard EncConverter +installed as part of SILConverters. Then +right-click on its small icon in the system tray and choose the Edit or Delete Converters menu item:

+ +

+ +

Figure 4: Clipboard EncConverter

+ +

In the resulting dialog, click the Add New button and then choose the NLLB Translator from the list and click the Add button:

+ +

+ +

Figure 5: Select and Add New Converter

+ +

 

+ +

This will bring up the Setup dialog for the NLLB Translate +EncConverter:

+ +

+ +

Figure 6: +NLLB Translator Setup 1, 2, 3, 4

+ +

 

+ +

1)      +This combo box is for selecting the Source +language of the input text for the translation operation.

+ +

2)      This +combo box is for selecting the Target language the input text should be +translated into.

+ +

3)      +If you want the converter to be permanently added to the +System Repository, then you must click the Save in System Repository button (see +below).

+ +

4)      +You can click on the Test Area tab to test the +converter with some sample data.

+ +

Saving the converter in the System Repository:

+ +

By default, if you click the Apply or OK +buttons, the configured converter will be returned to the client application as +a temporary converter for temporary use. Once the client application (e.g. FieldWorks or Word) is closed or releases the converter, it will no +longer be available. If you want the converter to be permanently available to +client applications, then you must explicitly add it to the System Repository using the Save in System +Repository button.

+ +

When you click this button, the following dialog box will +be displayed to query for a friendly name by +which the converter will be known in client applications:

+ +

+ +

 

+ +

The Advanced Tab can be used to enter further, +optional information about this converter, which is also put into the System Repository and can be used by various client +applications. Click on this tab to display the following dialog box:

+ +

+ +

 

+ +

Though these values are not necessary for the operation of +the converter, they can be helpful to various client applications. For example, +the Clipboard EncConverter can be configured to +filter the list of displayed converters based on the Encoding Name +and/or the Transduction Type configured here.

+ +
+ + + + diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/colorschememapping.xml b/redist/Help/NLLB_Translate_Plug-in_About_box_files/colorschememapping.xml new file mode 100644 index 00000000..6a0069cd --- /dev/null +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/filelist.xml b/redist/Help/NLLB_Translate_Plug-in_About_box_files/filelist.xml new file mode 100644 index 00000000..56881129 --- /dev/null +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/filelist.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/header.htm b/redist/Help/NLLB_Translate_Plug-in_About_box_files/header.htm new file mode 100644 index 00000000..b223218e --- /dev/null +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/header.htm @@ -0,0 +1,60 @@ + + + + + + + + + + + + + +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ + + + diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image003.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image003.jpg new file mode 100644 index 0000000000000000000000000000000000000000..04f9eb4c7bd2095720c4ee80d17d3c33d5ee75fa GIT binary patch literal 26809 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 Y|Jw3{#4?6gYh5!Hn literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image004.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5df2dff482189bb310e9ee13c96025a84ee45f20 GIT binary patch literal 8332 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 F{14s~d5{1A literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image007.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image007.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e38d449d78215a2d2d0284751e1aa529f5120d85 GIT binary patch literal 21741 zcmd?Q1yEhxk~Vy>puye4Ik*IOC%C&ya0%`ZI7lD~!QEYg2X}XOcXtRH^zie(_kQ>0 z&Yk zvf_d=JVL?(e+&YJjEs!-8jS=UokV~ZNGtIF{CjQ(U?4zwLX*KjQ2?MZpkOedp1T2L z000!+3$=d`{MR28Gz=`R)MSQt1sSlE}=J}=J!uo!TdZ&*ZL zVJW|dr*On(^^eLz0E$+0;HXUe1hE-A1t22f;^7kzQc_XV(9*GUaB^|;@QS??mync_ zmQhtx*U;3`)-f?PGqwRQCkjh$WHJ-vPX1A~)O(=)Sk^9zd`n_JsEyL z`3tPSA^SJDFkWy$!@|PA!vBE_3fldpz+k|_yMIDqg#fQ+yJz!Q18)1k8^=GtnAC{#& zfa{eC%^P8AYT^u?aMQTOXkd^;3?R;@*PH{Xvvy0!5vG)o>!Uy9+NIz zqwqGZAfhXwQdeP|-w}5?ClxhkNw6jk?3kZ%oLFr$Bz3B?K_LcH%$f!7(CZ0Lyz9r? z7$S|pCoZeL^cB^|5<0grEfottzwxUnJ}mA*dXhjJ;cl~7xsApu)i>FRS$M1WsKpea zF{7R!HymRgl~Gw;@9)xEbq=VK7M@hat9L7Fej=H*WsLZR zZHyOon&QibX@j|_SOxqO$IpP~uA?K!$F9?7K!6gLATM!>EVjfGBi(xQzL+;k{3Se~s7D@H2f4TOEMHLlQxhu1c&Tvjz=@1D{-5Tk?`_f+K?)pt$3@sjTjzb+Sq8&e#$dIPx6wZT&GJbClCXNa4KYh z>n;deSBcK4T5 z+_kEv@9;fY`+)SyQUeZf@L4X#C9tf)sA>*qHFEa!b$PAl4PsKoYvsl}94jV(COFt2 z*i zyFQsryFAp(v%bw$VDswui_!2}=EUg=-^l1}D zmS<(^n1{2AAJ}8LsT4CJ#gUsfQq&7<*{x38unjz8Xu5!wR5TyVDnYW z0HZ?0%J`RjuscIU$?wmnSZ>1qw;qB`ynl5_;pWxw(@F zoSP}+HcO_>vKnb{U4^cp=~5)}iU#6kR(Pz3Ty?X!b;b)!{I#qX4+DEJWy^C#Rzoh0 zAEEDZY$9`pSpx8c!YG1TT5G2=FUzU4jQjORrl>QE9Bvb&>g&T1>^H1T`IMn{B5K4o ztu&BzX>&o6B*${cP~3nEk1~7B)x-wrhe}&)fM>|e|V@Aqp_I<|BGrf$itDaC_wUn8(ZTlPNUbGgM5~L$G zI|#Q@)(z~oZ_Z^-7UuZ-U}MRo@1yuvNEjmbD1?Spvd;h!ZUB1|Ltf{PRb@f0Enn{`A%hwy8>Px9UQ|Vx06*ez6#pB9nz_{q;r6PnX;5ho(6@0kvZ+e9Y@$p)R-abA9R(-9W z0o@Zf+Ti^+o_7V$04(*L+D033MNSQmQ=Be%s3fRUFBReB&kJQ@RbOR%&%9~x?gsQ+ z3=&6}8J^+|?-30CI)c^92=0H5puKa=^On;eWN}s$FJHt3#w#aSS2MJjiAvhMd>1~@ zkp2#|P8^ELd3k-4OMge$W|jZ}p9!%)12!!m7}~DTn;)m10bh&Ib*)(p-nD*cGuJd; z3aLG=;J-j+33ZU#tvSdlm6=EhVz4c5zW8h-$u!BfFXJatd{c+)3WyRhkTMfc3(uTY zh*cZ;e!>#Xl*0FhC3W3Zs2jXk+-UgL;|Nl^$LI4i6YDNelvvw0q}<0FHO+)$rGtV- z(;1!BQ7ai7R(&F-#F2zK8^q>8Y7A2rqHHOpQA+QG@((ZH}~^-3ebAzP$)5X#tn z8&l`@cpjlQDdPHiFgRG;L5;bu;OX;p)FU)}lO2wiY7Dfr1>s>(YgT;i=^7*|RNG!E;JPB|*Tpxy(!Ks8k0FjD56Fv7Y)g*5A z*gZv-=Us_e2&KSqH1eN5VfONyBTTCsz<6m~E@#3~6G7$o)34614|LHea&3Xk2sw_% z9x$`{j=LJ>w;$g9xO56pI9xm_?DF&#dK|{ zZT`t~oL&8&EUCj=Z9uQ&nwD;@t+%w={TIeU) zEj8NC?E@sW?R>BtoPWEfQW-yaU`t3Kfe-DM?mYLi?8)Nmj7(kmTm7ssYveo_TxYAB2c9tLqR0-djtev_%t?X)tDGTwnT$L!8&7+0g6Ku{IH(RfODO)o-Uo8`kLjr} zgzN>iD;2e^?cm%YXTkNU%)QDMeUFb4UpQgf*XvHk;P+u`?z3CtF=B zEfjiK#0RyaED1Q?bm?7x^8}Z@XZ3{;RR8LK;9xm}=*}Mup?ew;`pe zlcimH9FP~WYpE9vbZ|_zmZbx`j%#CQnL7^wyYf^>0BeOf9+u1mdC1YFxzz99opv4_;LTSSGGhjwKfdo?Vbb7!yc-oA=wfj58l(?v>{MxG{Jw4ry1&+{ZeGphh950$l z{8{d4I+}KvA9<4682b3EKl*`L*oP+4z_;D;7b_la_e37UmCf(y&^86*`VW*>S8WcX zt?omuBm2j8+Y-`-bMudVI>O=HAr=pecgnlq%C$Iqg{Dt>A52sNQe(^10=o0RlBDE* z&_EAD^5Lp16Z1F9GCiy{R3NKX!4=5-&( zZgeklhMxguZFGP_Gc%5s>B$kAm|-P&y--}C2M*mh{&@rbEvLA#e9KFr1^dAWwx{^V z?=XJ)@Ji|MQ`g?OO&)6E79dLu3`tQ__=4}f9%b`dmHXM<(h0Z_h0EoWUhAauF0{E{|u;di6WV4t}xIa zHjQy2mA--C!1yO0{k{$wvpa<~@TfaB^-QmaHE~y!T{J{1w^1;8VBNRQi|_~yvRM0D zUA)E2`TM(sSnLzME%0v+=}mq^m@g92NYbs4jTeS4Gl~#((O|pew=WHkFBn@Onr328 zcQUC`zqZTLs}wl>>jPP5?LRQd=oEV)LkFAG=*P?ul)Re@>0<#&yBWg=B#*5+jIov( zVRv`(LVT!LCaCsNsOuwL!Qa^P{aB`gdZ zZ7H6lUr8uW=XX{^>th~pTpv-OG4TXh{`ejuEyTPJ=b2vc{gBN{$gFDo%sAcKRkv_* zA;vouev3E&N74>bbMmJw{zanQ-&cfu^3=00{ly-npk9$su*eTVudH#MKe51Mt?v~S zi4+%MN^rJ$*w1BE>~@TU_pi4d`=Pg6`}iC8ZN)UFezDsjYGEF%T~*yUnf5aUo!&XH z9gU)GsFkuKf5{P}9Jo~dGB4FQgXjnNoTq@EPQBmzSXdv&G*`TJ{za;8|5Y6!odb&oN1q9-MK_Va&h z1(jB`-=~@=v`9!Sp}I|+8tI&R(?|L_xs76TAr`ZniPe)T?f1@hA~sggq0t2Zb^KXn z{&(+gUk?B?OVR$+gnx2s!{Nq^G_9fWmY}*Z(SxU5sT}hl1%rfEna8Li=@VUCehfcW z=Y?GOn|4?xMCCSOaC_g5j_==B%mv+;1oy~wV2y|&Tni|3>!4MONL+3ZNIrf~vK_K- zr-u8@BCX+@OYcfSD9otW?AmWC2Y*j2S?S}#=&|jc*+){M^p*kmpSj;8nz)<=dfF{> zT`AS)?UvG48bdFfLl%CQE7B>+rrP-F>I3qiuNDkz%3=5;AQ(cE z3H?8ypbGWf5RS~`HF>zJG*nL`Gpk86NBfm5IZja%6At`*27DU}eWZ7`b#!(vIEu%| zLx#Dtk94d@Q&gUZ;LIH9#NsBm#t~;beVjEm@n2EHHbNvv=ix3h>}`dMm-m|LPJXpt zj%%trzqK_M8i~I(N8%${pX(nBq0~Pl#4X;KcUjR?@_$QpVGix&PD8^s=BvnY;L!ah z2#9iwZQ@*EE~Mf$m-wh9ZO`!xKt@cD?8?eHtU?kxZ@ z_c-53F%DPhaWwnOVgl6rx38(OTL)=RJ^O-PiyzKj-G)B{l+SUlxHK>umt-tRM0eE6 zB?h(%yspRqhmHAF8_2RFc33!Dr?9c}`XU<@OBBsp9q}6R5S()qozXCtU#g=gwnXy{ zasGx0@0a=nE?D%>y7=V1hB}pdHYH=1?>==`aUNjuqr4K*gW%`4^(#J(l!|FjWi>*E zlMmt#wTA8-PMN-rH!S^g5o z*3G<3dHEh#-L0hc)eR|X&CTY4AIyR}EA+VS64zs5de9WRaSO@<5MYS|$3t{R#~BKy zJ_-~p=nEwYv@}WrEqIJF2`BP@Vb0TJhlnB3Wc&SZDKv+R)r10-iVl^m>>(NC0|fjP zHzbNRT8)h%qbs{f0omc(DCzAMp~)jNF2Letp+!45heviMJtg(*^h0>xVqohXS$ zSLZc<^C|rtO2yVxyL^?8Z0h2$+~J6p20Jl?C&bH4-)A7M+%i|nm|e%r@2;ZPAY~G6 zO8TC}LAs;wax+sAEq==WWVc>D{vpBJAvWIb zn95+I+|Vt-6*{63RN12m{y92-Dm45sW*OVX{qA%zBbPpzJhV?*iZ&e6wR5jwSl(nA zF`KeNw{gK@dhKOyg`g8*9C2c`Q`R;H`y7rC_K{P`S@22v#u?M+CP|6rt1Ia+b~#0} z1s>=f3t}V_r69s>Q!=b*W4DW}*Ey_6`4$LpAL+R1@GTr^CUiRPETdh&QGgnC$CTbX z@IOgL$I!j~w9@^Kll3W|r#UIpLf!Iyqbe1Ldp%;`s>{%1qoVj5fm<9Z`D#jS%u%Xu z^|!2sVo+Jnmv^CzDbr5AV7vJv z(Rtovo$x}&0G+r>&-9JQmTYnTumDfc18MBTYYpTRZUbi|J5$FuFgEl!Kmj!1_ailq z*F;Lwn?ZJE43ro7n8)6t6Oq_{%!bS9t#Mc$+8JG#2aJwbNmQ3kKX=*hx=z%_kXZcK z7mS`9kT>x34Xw^KM2x z(mEm}n|Vu{I_byR-Vg{m@7Ru>K3N+5;)N=jC(^dlxLL{kWG;=Xq%K%cBlf;b$C`@^ zU38sY4##QeVO(9;Y5k)9{fN2cJwt(TYh{xn?P(W1pF~z-9C9=aMmtRX!R@r|20?DJ zWc1;(XK8}v$zUyi20h^P(em`w)qPxEYX;@zvV?7p$_PbTS45uDGvHIW5EZR_b&9@R zdCf#~eMj$BV0cTgqM^(OQevrU0+*K%qsO8Ird==vo&$M+dg9(`=%q3ma%41=)0a8Q zpwa#xB_$$nUiliNDR?FGeioI@zyhInzXDss?BJA(P^&DAAv_33Mn*5X4a=4GQ>?>foN5&m|zn zKz>o%&~|1O-l&5!t+0)ha)A}5lPDeS?M24^XMmPJxMe={VOp{yWjOQ~dQv)$A>RPs zL_pE`rOErH!L0^@%-1Ob)|02R-f5dOZ<4ZEr3SILhyzoNwv9`DDwiA#tHtZv;$NMo zt++k;6!Z3pUAR0f*$e=a>?u9*LAp3xP?4_`^F52^1o81y7vvooxG;sAOfR#!og>`= z`0wk_GA8{vG4CfOkP?{La2ElQn2H6n(R{Z=1DeU8=nt`C6w&in*N^n5bDg%f_5~6N z=*8Oo!z09$VgV1eCo2(l&W9{=H9tQ^iom{gh3Wl9SdVT(svEDL!8J4o>wFSA4lnt7 z8jr8}Yfge4*9V9BF}ck`*^+DK?@s}vDHI&-#8QX@$dp4dp>!>5>|#UtD0xVpYmz&`jfKp!B=VAK(pyueQm|wn?A-1Njv`j&q?% zUtai{^!EuA`FKk-HptSHl&*W6tVc6&0`v!d7-7w8R09bVrrZpF3JuH6K^CUM`l4=* z?74X&EE3u3QKBO9l)7K@3vy~hI|&RtestPBD7ARQks9&#)NqaYf|r22<9 ze21(dh7Ar7L;)BHqQscIEYf*rou!L-jPEV?{BSpfdyg}^Lt(Vs7g5VS-JOLN$cH;( z?Tust4!2slX%AMb3PfK&T*&VFS5?OEA`ob3=Y*wXngi0O15TH-xzj1a-E!>lP4)$B z;%BZ(H8mR9TGOmcY!}gz;=+-OU7rDdTjv}E12;3g;|ZuhAS?Jdau@)axZrOaI9m!aHmey$B=`Jc9K&0_kx@OCqjVTEYYTG9lk6f>eMD(R|^z`9G(lCvDC|++1lr zZK*~Q(CZSVLUpJ?t|-tIlN4KqEEShZCn4clcR zh1EnPGNWbv`u>*Vn=WT4+vgSLpg~s1ex!nKIy}x$&&HGb+noC7!BzRH+>wT0t?!OU zep0?g3~GBY2)8$(8GO@m!y*;wOUVI%Q>@d#Kw8AO8#!R%CPVg=sw=!I5FK&Fj1 zMtCF*zY36>oX#`TDK5e$%FYu=b7mVSdEXygE5AZ$Uji*qt`6Yti-e7k+OQS|ThA1qg7S z+r^zmzJI)5^YUu>i z)2NKO0QT}ulctrpF-AfD#)`d|Nr$Ihgq#MC0q4s)4NQgs-StX(flw?(g^PNEH+<7d z@2uY2U%tN%RQ6RAr43&aKbV_1I7pmkJ7K}BwED~0U9wG*yHmZe(}vNg)YLECS7O^J})so`NSrwVXrCtcwua666@ zCAGzEfQfisXr!*&!0cU5N!eHs9}N*NoSAYh{U7)Cekl zP7Rm)&?n%P)~#~i!ekg`I0H^R9c??A&F3N36V>3irw|Dmle<^bAPlj_{V7Xqm#y|T zxL3`Bc(Xy*7GAR^94BOO;bWY9mbPexhRG$$1@qoHVD{{Dsr?7r_{CEcSUp6TGTxt@ z;c4>XI_w*`TOf$BeC>w`ah!fFWpQl4|A?Xo4y$QuLA~kp%xtkmvw14geS00%MkH&J zRzIc)sgXC^Y~pqq5hy(~)QnM0n;b5iv48;u@4uSpcoeYI3FIxJPcS6a8X}DWp(}#C z;)Zl+*YWd+(c3djrZ`|ezN=PzEnmtJG!_MSP!$KI(%}ySOqY-+o4fwyKR2Pb-TD?| znX=$U{nt{Sl^o|VHhWYr6cegrU@GeNG;c!0)dia2iFuWl(bOp{LZ`5T@W9xdP>@UYe}-$I(%j#> zQf1b;C1f+aGqyDS_R)US$rBzp|Eomn5#H7^o^?TS$3S~!$SoTGB6QN>=m$p7fgc(^ z&dh``vGYfP5JsR}P31HwV7K#XwY2LU*~d@O3wq%^TT>*5ZIARxl0i)DiYE@8-eq`zqB*J@FWxF9l}X5Gf@o zVagUu`Rney;zzAgI6)gR=#0X@TQW`KhtLw-UO;WAPc#DXDNhJs~8Zri1 zodoYwn>_=-bB~t)P}$Y*nxBSf{vyQI0N>oaeC-wCd;0)s+mif;3hOCpZ^1=d{djf~ zcEuRx09JAD7Tur|!u6{RxsmIwWiIHX^SjpI*ZexzA@t^Yj`f2OoiUwm#t}? zgEjepy%Ai@TxapBoyf{KGL~n6=}pPE!Wy+{;~#j0(amj^%x|KZ&-@7_s2?)p$Lg$c zb1YnytIt6L$Wq@J{9;AB7~u6#Z_9WgL)}4Z6w;EX2r&~!+kweoJ+PvSj(XxD@<|IV&!WZ|r3z+tY4V2u*09)NV@%@lo~?PwuB@+hobQ~<8{@>{-PoB!9?beU>cqOp|nn!OQ{{QR+fK(pbj8hADPNTxE*UMat1x;RgI(_ zkhMpmI)~uEeZu7qTWG^j{uv;&nDKO#@u)727ND_{W;A1;NBb*4mdN&g~t369()?XK-f7;$k^_se2 zJ~nwO{00GcfTLs~I9F?zPleBbHR)$SkMc7B>E8YhGW`rV%YDhpDs~$r`G71!FQZ&X zz{RW~Tp|NAK<&WIpAM(>v-9xV>wy^!b%w)df3tPvPBXA{=$Nr(;oz<%VFLBMWXoIUs7@Pv)bgx{{+h%u` z9G!&+l3%Nihi_ILGq@57(5`8?Su8Q&zaP;31ozyiS?UgF>^!ob7D?3fTG?P?X{nq`2~F@s0;ds=wFk zejHv^+|gafw`qG>t9NdaTv~LLS{((&riyrvFVKhWKv}}o`>uwD{b6YG=JY(^B7d4x zCQgB8l{j3nRUTT>S-H;oC6a^bKPo5pd&XqjoFy*rXOGO z<%o$~?F@v5GHnw#=)|9#1wIJmM7MK2TVeXEa+#<;GijWny1xh^a+`i{XV4@SHN7S- zucUADRYFQqUaU?as65!>PM3$LSD?pCUH`3`7mv#_rE;GuqHplPPr=|x-md)R!S745 z$f3@+$%eNg>=E~{`r!4KAkb#9qO$C-sWORV-Qfqrv8prdE$(gSsrn*8i8d5_XU6Vq z;ZW3H%7hW*AD28kF8MC+RBs%P&8{CcA0NTq6faREEU9NeruZBL4h=#V_3?EM_uzph z$m?6y3wLXL{#@gsGP}KMh$H6kj?5+vITop5n;4_X-C4Q(CX^R68$YW_&pSHO%=+Eb zN_sGIfuHy$Ycl8t?f;fXP}Wmn&3CTntVquIpzDQ{{X5W)T@T$lw}qUtesig{FwoGh@8L^s1 z8p*$}hCE=VOb+@`jJIqv!;-K4y4N`*ehngY3MqUnj;NpBZJ5~&Cb1fxojYI3(q*|g zU8=`jir55}zZWL?JdXwOT7FSNyDzCvg6$cXvwM(d0N3pt3vNN-80RgAH0iuS-v@#d z97O6jbCIYbBtA!lEe+wb%gvSeUFiOudsZfXU{>C9;nxq);4$5dhsU)oDfWGT5dV65 zuFNu|W+(%F%`;leSzzRQmGpMHdNt}WPK+hM6szXKZLfxbH@}c$c!Kg|!k&X7fQK>X zYho;u^fEU-d=0V^Z^RGk$Loe?K-&m}BWd$BT=^A!lP;A#uR4*~;F5Gd|13v(aq$S! z08`c*M$F1SVhqzJnTep4DPmOL8iu+1o|f{FLWVihVL68{A-%xuU}M1>gst$FBK>5h zI7!69K9{rm#DfhXygpl;MuYAj-OM3XQPo}!)!`=4bwo%cZ}_wlXC zhHL}jinNo=%vL1mMt#v-er14rwe+9Y=N3FyAZ3(CV)K` zFKMM4cpaVr?aE_Zfsa}v4P_hV*IX!y7cY6gzt2*t?dl`(rd3~kT`GR-glIji7C)90 zfjHcUZY;RwTZ^o6kfD;zm*gG`SI$)fl5lQr0_>-Vl!vYdkwwTT*)0+?cmwPF^NYSO zfWUFxzHBE58KFXZPeMOw+d3PCaI6y+J!9wPX)H^1HX=dZqJ_P_cG3g;ENW%0wlc4I zt;m!bLe5RmK~#%8FfwYaOlpp){$pa&s*1&bOz{jDs|T;s47^B-VlUYxB;yu)Z9}FN z=RAbltWB=4e`JUhjG+%1NKmAk5=sT`D*4qq&e_X7Xo5JJo&m>KE%FLhM(NvKc5CKZ zznGS{19GoXc-?XqJlmRus>vQ7K0~0t38MY%IgKLOyNONo%tb}P;^HUX%X2}4Yj%<( zPEaX{wlJ>gf}THm@ulfS8m7%#!|XW_PL)exyCn&OmbJnW0Ot{79Fo0FVbh2t9l>s2 zR}q=vW7WdlZB3>_Z`zAP)i9;D%MG+b!gK2^lN7Weu9N)i7#l&y@N|lBGhdjd0iRhnJ#+BCAp#t&66TtcS=9kU9#M2^k z4X=A%g7=ig>;QEH@&~ceNm;>nC7BE*0GN68`vOa-@O_pya^=yeEVnnA@IL-Rd!=Jf z5c~5?tMkxJS^xCt2Y7XnR_k25-3V(BPA9Gy+ahaAKZ}*;72ZJK)oUGY#>V6?s9-i?9!J*198% ztyG#u!o6Zs9^Y3$01LueP?&o02k<+OAjBi#uFAize)k(E|oe&<{Nz>z+ z)0yg%PE3MlXGWI#cG?yN)lu>N)|lMGQvHuKYr-6>m(D1Sw8@Tp&7N-9E{me7TG>*s zPn1>ohrCI&JF0EN~Y<4HK!}u7xMVDRptago<74L z1F>&kI^wp!``PxBmUv)R%@6I)nK14wld_AYoaoZvDG-&J@wVD=BeM%iv#b zsx1E(8{13~ZKV3&w<^iso7IQ|{+k|2nAv8iSPe@2%3GRA$0w8| zPdbqv9l2bhPwxJHUA+M)onyHp?(#lZg8)`_KNCs$Kx1}{IKBe(7R4?q2w%BAz=`i7 zyXv^wJE`10cP6JUnkX{q8(;6v7H|h2|Jcdr$Snjg64-U`(<~_GVEmSTa3RL8=^Kid zQ92z>GfTd>g+PulWnHpHVs3#i$>(7a{>xKEow;m39h~E1+hZWDEoSBiJ94LP02FmY zI}U12j@Dt*>zzia^GN0MOC|(02-(CsRNFR7MPc)uk#p+HA%y)*1h}*x zy^I_9V761VmZ!7w7KYmR%i4p?5Q(KaCcjiKAG((qRI3g)Vuc&Zd&l-Z8PoWmgDId8 zF8!t2$^f>b>q5&+gx6^m#=WbUvi6|Nht)PiFUzS9!7LVbETO&!9(@Wk<{^M#Ubuv% z$ph>xJ!6h`1zyK+Ary_Yf3|D?$=3Z{26T#Q*Uo==LSCXh`xJi2f8%*|jlWvDMKk|! zIPrJ4@;`E|VSk4t{&Muu@EIVgQ>FgD7Lz; z{p~~ZGr$LYg`rVYTKDL)3T|z?N63W!8yNMvXF$Y5TM?M9=3jEwzv8&x@BiPqPnYb@ z;~7wP@cav|MFVB_T_Cfjs1E#1SNuFU9<%5TiJVfIeV2E0$}_b9Ch8lai!XS zCS3i0`au1TZ?iOK=fsi50^> zUVodYVjEaMY%!UIdhCGd5$4gM*MUo8sIB812 zYv3{D^2Zk=;%MS)+g{L1gy0!)y$@p?(rX@vk(SlCm_v={)5hBv?>Io%IN}@(h*;yg z9fupF`(qFH*89Ub{fqfn_F_IN!4>^)yKmFj8?+Ko6dLWV4t{ZnZ~km|t~M{B zzhGdx>W*IdgW&#u;hO$;@zC!|@eeE1<|SY<1Hv7!Z+q{gxAU#S*rN}e2T&!uzFn=a)p_x|Kx7`y-i@Lu#cq8?8$1;HIP7-%|)TU|IxlpGa@7-RnSX zg^6oc%iS%?yQ~w!`|DViDrGdCiWO=w!y)15*YWH~rTII-xDMfn`q+|`i21k&@$cc+nh4WgVK zU32sWx&wquDf-BbmSRzl0k20TgnR6Dzzw5iP(#ndsi3P_@7i=)L6-k8AD|wa5xi`~~e7F_wiN>&h+!d0FR$LRO zLi4tn*A+Kn6uWj%hlAL z|JB~bo+k;?sQ{p3;6OZJPefex!5eIo^0rdX)0m9wM2l3zIV@?^-TgpgAIkDO(;4Hj zEoEb45=8(d!)YIs@R4GG$Ei`cRwAoZR_uMCFs8C}y;le#41s_plw}dC^-ZCxqZQHJ zoP*dNKSrb>@w$%!Hx6UiLi3M+U0F}tWObDHiGY1YV*yL(5$q&_Ue6qI_akBC|H^Li z|Je5xRfGGUzV3liZ?r7SC5gEvMkU$?19oW4(m3HZKbrH~&zW-{1;E%taMjV$7Ifl3 ziT*B1oZ8F4yY0C=W#LoLx-RhR#WfFISzB$UMIT;^I7U0{>~}j~U)RA<6Nkpkmfm9A z+z$1Go{xTYcc~N}LoVviM3({?HyzThseJHk`$A5=Nm@u=8<*wtN-8NHmu}MHjngY+ z6P$<*WS$d_QUrt=gipx~QTlZWRPU0w4J2Ry+&IVBDhKvQ<#%!5qnBh5;2;xwn(`y^ zru>^@$kL6632vPnl&KM_mPI7I>WH->cC^i+&JibG zofl(o3^DqhGM^{gPw6+F8r;37EJw2~Od+@#bLDrRukXN7yLCF&9b0I)(t=5};d^po z_HP%40^XUDCBj@oxWn0u8Z!dN}o%v$D?&Fw(mIpErO47~{p3C-eJbe!U##8yIh$=3(`|5i#C zIAmkbiFut463}cxuQXa=JuTa}-v4?rUO1ZWJ}?3;leveZVOfWMDH)|+!$boJ$W6yz z#o-Lk+qfr(XBvfD=7?EGzcCYC3fZG{-;O9Cy{^cScXZ6t9dW0SW(XmUl@CmxAIM}f z$ZmKN>z0)J5&twUj~#_pnp6>qDcQXES^aAOELm^^eH#~u&09q z{#ziNG_XxfVR2qkO#JSm|6B}QLl-gf{Z`X?mBo6(F2%J`;&YD!#+j;pAlgziYL{H?BY-zhHwLEZ9MHk!w zu*gBdn9Ymm4xO9jY%>p$s24s1X(B0$fIjAKxhptMt@?3&FCi*b(JI+!_U^6=*X_nA zwuQ=Oz=IdeVeI1|@+f!9b2fv^jF(DN;k^7ooPgxqs|owCR|DM=9ul&fd+x72$zF-# zJ8VZx@Ix4>JBY}0$8nm}OJ&((aFse#93jnMYhXD#qUi#@mgc<|OHkL>7aD>1TLKs9xu( zipRpn)dJE4(@J^F!AdFM;_3GWo4xy3fB=*_ahUV=lCu*5GR4NG+Q=e3VtL*V<_ucjx57Qm@JVZmIV$z| z<*5{7AKKvq9Q`v!tL*tX%v>&I{5R4yQ6?F}qAux)QGP0P^k<>Ozm{1!vo)>>M0O;K z-a*2sep<$u1O1euh&bWn)Z{`aCQL#xEnDAU#t#>e-YR^Fd>Sv>`%jOC*_BkprS-B+ zN2Ox=C|H~1FA;fr=L_e184BKJVB2b0{PkuFX!l!VsN!Fw8LKgM=`B zP=x~x4-ta>g=a6_ex~-XpbiWGjiLI_QAWZ_XYf`U+f6`WDJ+U}Peb|Id}!z5`5WR@ zXvDjlOgkp}rrGWFx`M90m*~qX7S`*%0;6>LNLx1Z`FgwQ_t8!rlonP#pZsRBG%1IG zANPwE15|e?w;&&?Ei>NFzj{It9@}ha2_K~Z_FUIJgV4@}K9Qb_NU*ZP@UTN2j+JaA zS4qPkn*fvVPgmbO*<5HL_0uxWu5+Meq z7hW{m3MU8jZS8>5pqf;5#;efxWKC?$<;Wjg6YZnTW{yKN=)QT(NtLYDD?ww-}C+%@m|2dljTXd|j zZos#BdTt>~{Tp*ys9zmT5pjDsyK}_k!%;*xO{1vhh>`vJh6%|#N4i`d!s{FuUq z*zq)+*W~6|mM7kw5=}7N?=vfA;@^*9;>~mMdg(@x8MgNgn-rH6Qg_GbC})~RYc*`H z@K$}3tMb#33xY2VY>)S-eSaY)U7&vsM%k3}G@M6_+L%$AoLkUbZ$DeCyX1yht~gL< zRFE_q2yER{+!|Os4*Ut4YV&yA9LR+)9Z!^T)B|lhAC*;0Ee0WO-^}@}YBGY+1ayrf zn*uP#(w0K&asdeK5_;AT%}0iNc9RqvWt|g#gXZZVV4$+%v+Np0(K#g#RHZLg(;rkQ zgAAZE%O$`}S^Ij5^rN)evpanu0o=_C>jGe2m>*AOR%aEhl0ph!|GxtK0 zpe7QDgtbK{pJ-#PD%8o}v%O$z<5d^-B7={z8ZEfe|ODaO5SC_*q8kjVt=f97v}I zei14CqycvVgzSYtU>rg(Vmu2 XldG3eMTfBey`cFY8|8nT_4nvMOsd%( literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image008.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image008.jpg new file mode 100644 index 0000000000000000000000000000000000000000..11fb33471fe10dfc3acdceb4f83c6b3e30e26bef GIT binary patch literal 13022 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 BHc$Wn literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image012.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image012.jpg new file mode 100644 index 0000000000000000000000000000000000000000..11783c43f40b381be9e95d368a5d316714faa5f0 GIT binary patch literal 37473 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 literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image013.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image013.jpg new file mode 100644 index 0000000000000000000000000000000000000000..be484b16247b3712d68d5ce830ea28d47b5d30fb GIT binary patch literal 17852 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 literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image016.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image016.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ce3b3c12aac804fccf0b740d0190e98ea1d44ec GIT binary patch literal 10763 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

o^vjeUu%A^;>G!rmNp3mOQPK@@a+&5Sv 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 literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image021.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image021.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cdad918c32514a72f744399f52d1e487c67d8d0d GIT binary patch literal 24954 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 N|BjNA7y5-i{tCpwR*C=s literal 0 HcmV?d00001 diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/item0015.xml b/redist/Help/NLLB_Translate_Plug-in_About_box_files/item0015.xml new file mode 100644 index 00000000..df14848b --- /dev/null +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/item0015.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/item0023.xml b/redist/Help/NLLB_Translate_Plug-in_About_box_files/item0023.xml new file mode 100644 index 00000000..df14848b --- /dev/null +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/item0023.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/props016.xml b/redist/Help/NLLB_Translate_Plug-in_About_box_files/props016.xml new file mode 100644 index 00000000..9621d74e --- /dev/null +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/props016.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/props024.xml b/redist/Help/NLLB_Translate_Plug-in_About_box_files/props024.xml new file mode 100644 index 00000000..9621d74e --- /dev/null +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/props024.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/themedata.thmx b/redist/Help/NLLB_Translate_Plug-in_About_box_files/themedata.thmx new file mode 100644 index 0000000000000000000000000000000000000000..3d2a4372ca5888704157184c6edc22884c62dae9 GIT binary patch literal 3339 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 literal 0 HcmV?d00001 diff --git a/src/EcTranslators/DeepLTranslator/DeepL/Internal/DeepLClient.cs b/src/EcTranslators/DeepLTranslator/DeepL/Internal/DeepLClient.cs index e18009d1..d82bef78 100644 --- a/src/EcTranslators/DeepLTranslator/DeepL/Internal/DeepLClient.cs +++ b/src/EcTranslators/DeepLTranslator/DeepL/Internal/DeepLClient.cs @@ -12,6 +12,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; +using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; @@ -294,15 +295,39 @@ public async Task ApiPostAsync( return await ApiCallAsync(requestMessage, cancellationToken); } - ///

Internal function to upload files using an HTTP POST request. - /// Endpoint URL relative to server base URL. - /// The cancellation token to cancel operation. - /// Parameters to embed in the HTTP request body. - /// Optional file content to upload in request. - /// If is used, the name of file. - /// received from DeepL API. - /// If any failure occurs while sending the request. - public async Task ApiUploadAsync( + /// Function to perform HTTP POST requests using a simple json contents (used by NllbTranslator; not DeepL). + /// Endpoint URL relative to server base URL. + /// The cancellation token to cancel operation. + /// Parameters to embed in the HTTP request body. + /// received from DeepL API. + /// If any failure occurs while sending the request. + public async Task ApiPostJsonAsync( + string relativeUri, + CancellationToken cancellationToken, + object? bodyObject = null) + { + var requestBody = bodyObject != null + ? Newtonsoft.Json.JsonConvert.SerializeObject(bodyObject) + : null; + + using var requestMessage = new HttpRequestMessage + { + RequestUri = new Uri(_serverUrl, relativeUri), + Method = HttpMethod.Post, + Content = new StringContent(requestBody, Encoding.UTF8, "application/json") + }; + return await ApiCallAsync(requestMessage, cancellationToken); + } + + /// Internal function to upload files using an HTTP POST request. + /// Endpoint URL relative to server base URL. + /// The cancellation token to cancel operation. + /// Parameters to embed in the HTTP request body. + /// Optional file content to upload in request. + /// If is used, the name of file. + /// received from DeepL API. + /// If any failure occurs while sending the request. + public async Task ApiUploadAsync( string relativeUri, CancellationToken cancellationToken, IEnumerable<(string Key, string Value)> bodyParams, diff --git a/src/EcTranslators/DeepLTranslator/DeepL/LICENSE b/src/EcTranslators/DeepLTranslator/DeepL/LICENSE new file mode 100644 index 00000000..906c2248 --- /dev/null +++ b/src/EcTranslators/DeepLTranslator/DeepL/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright 2022 DeepL SE (https://www.deepl.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/EcTranslators/EcTranslators.csproj b/src/EcTranslators/EcTranslators.csproj index a4737d71..d9e299d7 100644 --- a/src/EcTranslators/EcTranslators.csproj +++ b/src/EcTranslators/EcTranslators.csproj @@ -27,7 +27,7 @@ true $(SolutionDir)output\$(Platform)\$(Configuration)\ - DEBUG;TRACE + TRACE;DEBUG;X64 full x64 8.0 @@ -35,7 +35,7 @@ $(SolutionDir)output\$(Platform)\$(Configuration)\ - TRACE + TRACE;X64 true pdbonly x64 @@ -152,6 +152,16 @@ QueryForGoogleCredentials.cs + + Form + + + NllbTranslatorAutoConfigDialog.cs + + + + + True @@ -197,6 +207,9 @@ QueryForGoogleCredentials.cs + + NllbTranslatorAutoConfigDialog.cs + ResXFileCodeGenerator Resources.Designer.cs @@ -214,6 +227,8 @@ FieldWorks.snk + + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/src/EcTranslators/NllbTranslator/NllbHumanReadableLgNames.json b/src/EcTranslators/NllbTranslator/NllbHumanReadableLgNames.json new file mode 100644 index 00000000..6135652f --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbHumanReadableLgNames.json @@ -0,0 +1,806 @@ +[ + { + "Code": "zul_Latn", + "Name": "Zulu (Latin script)" + }, + { + "Code": "zsm_Latn", + "Name": "Standard Malay (Latin script)" + }, + { + "Code": "zho_Hant", + "Name": "Chinese (Traditional Han script)" + }, + { + "Code": "zho_Hans", + "Name": "Chinese (Simplified Han script)" + }, + { + "Code": "yue_Hant", + "Name": "Cantonese (Traditional Han script)" + }, + { + "Code": "yor_Latn", + "Name": "Yoruba (Latin script)" + }, + { + "Code": "ydd_Hebr", + "Name": "Yiddish (Hebrew script)" + }, + { + "Code": "xho_Latn", + "Name": "Xhosa (Latin script)" + }, + { + "Code": "wol_Latn", + "Name": "Wolof (Latin script)" + }, + { + "Code": "war_Latn", + "Name": "Waray (Latin script)" + }, + { + "Code": "vie_Latn", + "Name": "Vietnamese (Latin script)" + }, + { + "Code": "vec_Latn", + "Name": "Venetian (Latin script)" + }, + { + "Code": "uzn_Latn", + "Name": "Uzbek (Latin script)" + }, + { + "Code": "urd_Arab", + "Name": "Urdu (Arabic script)" + }, + { + "Code": "umb_Latn", + "Name": "Umbundu (Latin script)" + }, + { + "Code": "ukr_Cyrl", + "Name": "Ukrainian (Cyrillic script)" + }, + { + "Code": "uig_Arab", + "Name": "Uyghur (Arabic script)" + }, + { + "Code": "tzm_Tfng", + "Name": "Central Atlas Tamazight (Tifinagh script)" + }, + { + "Code": "twi_Latn", + "Name": "Twi (Latin script)" + }, + { + "Code": "tur_Latn", + "Name": "Turkish (Latin script)" + }, + { + "Code": "tum_Latn", + "Name": "Tumbuka (Latin script)" + }, + { + "Code": "tuk_Latn", + "Name": "Turkmen (Latin script)" + }, + { + "Code": "tso_Latn", + "Name": "Tsonga (Latin script)" + }, + { + "Code": "tsn_Latn", + "Name": "Tswana (Latin script)" + }, + { + "Code": "tpi_Latn", + "Name": "Tok Pisin (Latin script)" + }, + { + "Code": "tir_Ethi", + "Name": "Tigrinya (Ethiopic script)" + }, + { + "Code": "tha_Thai", + "Name": "Thai (Thai script)" + }, + { + "Code": "tgl_Latn", + "Name": "Tagalog (Latin script)" + }, + { + "Code": "tgk_Cyrl", + "Name": "Tajik (Cyrillic script)" + }, + { + "Code": "tel_Telu", + "Name": "Telugu (Telugu script)" + }, + { + "Code": "tat_Cyrl", + "Name": "Tatar (Cyrillic script)" + }, + { + "Code": "taq_Tfng", + "Name": "Tamasheq (Tifinagh script)" + }, + { + "Code": "taq_Latn", + "Name": "Tamasheq (Latin script)" + }, + { + "Code": "tam_Taml", + "Name": "Tamil (Tamil script)" + }, + { + "Code": "szl_Latn", + "Name": "Silesian (Latin script)" + }, + { + "Code": "swh_Latn", + "Name": "Swahili (Latin script)" + }, + { + "Code": "swe_Latn", + "Name": "Swedish (Latin script)" + }, + { + "Code": "sun_Latn", + "Name": "Sundanese (Latin script)" + }, + { + "Code": "ssw_Latn", + "Name": "Swazi (Latin script)" + }, + { + "Code": "srp_Cyrl", + "Name": "Serbian (Cyrillic script)" + }, + { + "Code": "srd_Latn", + "Name": "Sardinian (Latin script)" + }, + { + "Code": "spa_Latn", + "Name": "Spanish (Latin script)" + }, + { + "Code": "sot_Latn", + "Name": "Sotho (Latin script)" + }, + { + "Code": "som_Latn", + "Name": "Somali (Latin script)" + }, + { + "Code": "snd_Arab", + "Name": "Sindhi (Arabic script)" + }, + { + "Code": "sna_Latn", + "Name": "Shona (Latin script)" + }, + { + "Code": "smo_Latn", + "Name": "Samoan (Latin script)" + }, + { + "Code": "slv_Latn", + "Name": "Slovenian (Latin script)" + }, + { + "Code": "slk_Latn", + "Name": "Slovak (Latin script)" + }, + { + "Code": "sin_Sinh", + "Name": "Sinhala (Sinhala script)" + }, + { + "Code": "shn_Mymr", + "Name": "Shan (Myanmar script)" + }, + { + "Code": "scn_Latn", + "Name": "Sicilian (Latin script)" + }, + { + "Code": "sat_Beng", + "Name": "Santali (Bengali script)" + }, + { + "Code": "san_Deva", + "Name": "Sanskrit (Devanagari script)" + }, + { + "Code": "sag_Latn", + "Name": "Sango (Latin script)" + }, + { + "Code": "rus_Cyrl", + "Name": "Russian (Cyrillic script)" + }, + { + "Code": "run_Latn", + "Name": "Rundi (Latin script)" + }, + { + "Code": "ron_Latn", + "Name": "Romanian (Latin script)" + }, + { + "Code": "quy_Latn", + "Name": "Ayacucho Quechua (Latin script)" + }, + { + "Code": "prs_Arab", + "Name": "Dari (Arabic script)" + }, + { + "Code": "por_Latn", + "Name": "Portuguese (Latin script)" + }, + { + "Code": "pol_Latn", + "Name": "Polish (Latin script)" + }, + { + "Code": "plt_Latn", + "Name": "Malagasy (Latin script)" + }, + { + "Code": "pes_Arab", + "Name": "Western Farsi (Arabic script)" + }, + { + "Code": "pbt_Arab", + "Name": "Northern Pashto (Arabic script)" + }, + { + "Code": "pap_Latn", + "Name": "Papiamento (Latin script)" + }, + { + "Code": "pan_Guru", + "Name": "Punjabi (Gurmukhi script)" + }, + { + "Code": "pag_Latn", + "Name": "Pangasinan (Latin script)" + }, + { + "Code": "ory_Orya", + "Name": "Odia (Oriya script)" + }, + { + "Code": "oci_Latn", + "Name": "Occitan (Latin script)" + }, + { + "Code": "nya_Latn", + "Name": "Chichewa (Latin script)" + }, + { + "Code": "nus_Latn", + "Name": "Nuer (Latin script)" + }, + { + "Code": "npi_Deva", + "Name": "Nepali (Devanagari script)" + }, + { + "Code": "nob_Latn", + "Name": "Norwegian (Bokmål, Latin script)" + }, + { + "Code": "nno_Latn", + "Name": "Norwegian (Nynorsk, Latin script)" + }, + { + "Code": "nld_Latn", + "Name": "Dutch (Latin script)" + }, + { + "Code": "mya_Mymr", + "Name": "Burmese (Myanmar script)" + }, + { + "Code": "mri_Latn", + "Name": "Maori (Latin script)" + }, + { + "Code": "mos_Latn", + "Name": "Mossi (Latin script)" + }, + { + "Code": "mni_Beng", + "Name": "Manipuri (Bengali script)" + }, + { + "Code": "mlt_Latn", + "Name": "Maltese (Latin script)" + }, + { + "Code": "mkd_Cyrl", + "Name": "Macedonian (Cyrillic script)" + }, + { + "Code": "min_Latn", + "Name": "Minangkabau (Latin script)" + }, + { + "Code": "mar_Deva", + "Name": "Marathi (Devanagari script)" + }, + { + "Code": "mal_Mlym", + "Name": "Malayalam (Malayalam script)" + }, + { + "Code": "mai_Deva", + "Name": "Maithili (Devanagari script)" + }, + { + "Code": "mag_Deva", + "Name": "Magahi (Devanagari script)" + }, + { + "Code": "lvs_Latn", + "Name": "Latvian (Latin script)" + }, + { + "Code": "lus_Latn", + "Name": "Mizo (Latin script)" + }, + { + "Code": "luo_Latn", + "Name": "Luo (Latin script)" + }, + { + "Code": "lug_Latn", + "Name": "Luganda (Latin script)" + }, + { + "Code": "lua_Latn", + "Name": "Luba-Kasai (Latin script)" + }, + { + "Code": "ltz_Latn", + "Name": "Luxembourgish (Latin script)" + }, + { + "Code": "ltg_Latn", + "Name": "Latgalian (Latin script)" + }, + { + "Code": "lmo_Latn", + "Name": "Lombard (Latin script)" + }, + { + "Code": "lit_Latn", + "Name": "Lithuanian (Latin script)" + }, + { + "Code": "lin_Latn", + "Name": "Lingala (Latin script)" + }, + { + "Code": "lim_Latn", + "Name": "Limburgish (Latin script)" + }, + { + "Code": "lij_Latn", + "Name": "Ligurian (Latin script)" + }, + { + "Code": "lao_Laoo", + "Name": "Lao (Lao script)" + }, + { + "Code": "kor_Hang", + "Name": "Korean (Hangul script)" + }, + { + "Code": "kon_Latn", + "Name": "Kongo (Latin script)" + }, + { + "Code": "knc_Latn", + "Name": "Central Kanuri (Latin script)" + }, + { + "Code": "knc_Arab", + "Name": "Central Kanuri (Arabic script)" + }, + { + "Code": "kmr_Latn", + "Name": "Northern Kurdish (Latin script)" + }, + { + "Code": "kmb_Latn", + "Name": "Kimbundu (Latin script)" + }, + { + "Code": "kir_Cyrl", + "Name": "Kyrgyz (Cyrillic script)" + }, + { + "Code": "kin_Latn", + "Name": "Kinyarwanda (Latin script)" + }, + { + "Code": "kik_Latn", + "Name": "Kikuyu (Latin script)" + }, + { + "Code": "khm_Khmr", + "Name": "Khmer (Khmer script)" + }, + { + "Code": "khk_Cyrl", + "Name": "Khakass (Cyrillic script)" + }, + { + "Code": "kea_Latn", + "Name": "Kabuverdianu (Latin script)" + }, + { + "Code": "kbp_Latn", + "Name": "Kabiye (Latin script)" + }, + { + "Code": "kaz_Cyrl", + "Name": "Kazakh (Cyrillic script)" + }, + { + "Code": "kat_Geor", + "Name": "Georgian (Georgian script)" + }, + { + "Code": "kas_Deva", + "Name": "Kashmiri (Devanagari script)" + }, + { + "Code": "kas_Arab", + "Name": "Kashmiri (Arabic script)" + }, + { + "Code": "kan_Knda", + "Name": "Kannada (Kannada script)" + }, + { + "Code": "kam_Latn", + "Name": "Kamba (Latin script)" + }, + { + "Code": "kac_Latn", + "Name": "Kachin (Latin script)" + }, + { + "Code": "kab_Latn", + "Name": "Kabyle (Latin script)" + }, + { + "Code": "jpn_Jpan", + "Name": "Japanese (Japanese script)" + }, + { + "Code": "jav_Latn", + "Name": "Javanese (Latin script)" + }, + { + "Code": "ita_Latn", + "Name": "Italian (Latin script)" + }, + { + "Code": "isl_Latn", + "Name": "Icelandic (Latin script)" + }, + { + "Code": "ind_Latn", + "Name": "Indonesian (Latin script)" + }, + { + "Code": "ilo_Latn", + "Name": "Iloko (Latin script)" + }, + { + "Code": "ibo_Latn", + "Name": "Igbo (Latin script)" + }, + { + "Code": "hye_Armn", + "Name": "Armenian (Armenian script)" + }, + { + "Code": "hun_Latn", + "Name": "Hungarian (Latin script)" + }, + { + "Code": "hrv_Latn", + "Name": "Croatian (Latin script)" + }, + { + "Code": "hne_Deva", + "Name": "Chhattisgarhi (Devanagari script)" + }, + { + "Code": "hin_Deva", + "Name": "Hindi (Devanagari script)" + }, + { + "Code": "heb_Hebr", + "Name": "Hebrew (Hebrew script)" + }, + { + "Code": "hau_Latn", + "Name": "Hausa (Latin script)" + }, + { + "Code": "hat_Latn", + "Name": "Haitian Creole (Latin script)" + }, + { + "Code": "guj_Gujr", + "Name": "Gujarati (Gujarati script)" + }, + { + "Code": "grn_Latn", + "Name": "Guarani (Latin script)" + }, + { + "Code": "glg_Latn", + "Name": "Galician (Latin script)" + }, + { + "Code": "gle_Latn", + "Name": "Irish (Latin script)" + }, + { + "Code": "gla_Latn", + "Name": "Scottish Gaelic (Latin script)" + }, + { + "Code": "gaz_Latn", + "Name": "West Central Oromo (Latin script)" + }, + { + "Code": "fuv_Latn", + "Name": "Nigerian Fulfulde (Latin script)" + }, + { + "Code": "fur_Latn", + "Name": "Friulian (Latin script)" + }, + { + "Code": "fra_Latn", + "Name": "French (Latin script)" + }, + { + "Code": "fon_Latn", + "Name": "Fon (Latin script)" + }, + { + "Code": "fin_Latn", + "Name": "Finnish (Latin script)" + }, + { + "Code": "fij_Latn", + "Name": "Fijian (Latin script)" + }, + { + "Code": "fao_Latn", + "Name": "Faroese (Latin script)" + }, + { + "Code": "ewe_Latn", + "Name": "Ewe (Latin script)" + }, + { + "Code": "eus_Latn", + "Name": "Basque (Latin script)" + }, + { + "Code": "est_Latn", + "Name": "Estonian (Latin script)" + }, + { + "Code": "epo_Latn", + "Name": "Esperanto (Latin script)" + }, + { + "Code": "eng_Latn", + "Name": "English (Latin script)" + }, + { + "Code": "ell_Grek", + "Name": "Greek (Greek script)" + }, + { + "Code": "dzo_Tibt", + "Name": "Dzongkha (Tibetan script)" + }, + { + "Code": "dyu_Latn", + "Name": "Dyula (Latin script)" + }, + { + "Code": "dik_Latn", + "Name": "Dinka (Latin script)" + }, + { + "Code": "deu_Latn", + "Name": "German (Latin script)" + }, + { + "Code": "dan_Latn", + "Name": "Danish (Latin script)" + }, + { + "Code": "cym_Latn", + "Name": "Welsh (Latin script)" + }, + { + "Code": "crh_Latn", + "Name": "Crimean Tatar (Latin script)" + }, + { + "Code": "ckb_Arab", + "Name": "Central Kurdish (Arabic script)" + }, + { + "Code": "cjk_Latn", + "Name": "Korean (Latin script)" + }, + { + "Code": "ces_Latn", + "Name": "Czech (Latin script)" + }, + { + "Code": "ceb_Latn", + "Name": "Cebuano (Latin script)" + }, + { + "Code": "cat_Latn", + "Name": "Catalan (Latin script)" + }, + { + "Code": "bul_Cyrl", + "Name": "Bulgarian (Cyrillic script)" + }, + { + "Code": "bug_Latn", + "Name": "Buginese (Latin script)" + }, + { + "Code": "bos_Latn", + "Name": "Bosnian (Latin script)" + }, + { + "Code": "bod_Tibt", + "Name": "Tibetan (Tibetan script)" + }, + { + "Code": "bjn_Latn", + "Name": "Banjar (Latin script)" + }, + { + "Code": "bjn_Arab", + "Name": "Banjar (Arabic script)" + }, + { + "Code": "bho_Deva", + "Name": "Bhojpuri (Devanagari script)" + }, + { + "Code": "ben_Beng", + "Name": "Bengali (Bengali script)" + }, + { + "Code": "bem_Latn", + "Name": "Bemba (Latin script)" + }, + { + "Code": "bel_Cyrl", + "Name": "Belarusian (Cyrillic script)" + }, + { + "Code": "ban_Latn", + "Name": "Balinese (Latin script)" + }, + { + "Code": "bam_Latn", + "Name": "Bambara (Latin script)" + }, + { + "Code": "bak_Cyrl", + "Name": "Bashkir (Cyrillic script)" + }, + { + "Code": "azj_Latn", + "Name": "North Azerbaijani (Latin script)" + }, + { + "Code": "azb_Arab", + "Name": "South Azerbaijani (Arabic script)" + }, + { + "Code": "ayr_Latn", + "Name": "Central Aymara (Latin script)" + }, + { + "Code": "awa_Deva", + "Name": "Awadhi (Devanagari script)" + }, + { + "Code": "ast_Latn", + "Name": "Asturian (Latin script)" + }, + { + "Code": "asm_Beng", + "Name": "Assamese (Bengali script)" + }, + { + "Code": "arz_Arab", + "Name": "Egyptian Arabic (Arabic script)" + }, + { + "Code": "ary_Arab", + "Name": "Moroccan Arabic (Arabic script)" + }, + { + "Code": "ars_Arab", + "Name": "Najdi Arabic (Arabic script)" + }, + { + "Code": "arb_Arab", + "Name": "Standard Arabic (Arabic script)" + }, + { + "Code": "apc_Arab", + "Name": "Palestinian Arabic (Arabic script)" + }, + { + "Code": "amh_Ethi", + "Name": "Amharic (Ethiopian script)" + }, + { + "Code": "als_Latn", + "Name": "Tosk Albanian (Latin script)" + }, + { + "Code": "aka_Latn", + "Name": "Akan (Latin script)" + }, + { + "Code": "ajp_Arab", + "Name": "South Levantine Arabic (Arabic script)" + }, + { + "Code": "afr_Latn", + "Name": "Afrikaans (Latin script)" + }, + { + "Code": "aeb_Arab", + "Name": "Tunisian Arabic (Arabic script)" + }, + { + "Code": "acq_Arab", + "Name": "Ta'izzi-Adeni Arabic (Arabic script)" + }, + { + "Code": "acm_Arab", + "Name": "Iraqi Arabic (Arabic script)" + }, + { + "Code": "ace_Latn", + "Name": "Acehnese (Latin script)" + }, + { + "Code": "ace_Arab", + "Name": "Acehnese (Arabic script)" + } +] \ No newline at end of file diff --git a/src/EcTranslators/NllbTranslator/NllbLanguage.cs b/src/EcTranslators/NllbTranslator/NllbLanguage.cs new file mode 100644 index 00000000..67672e89 --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbLanguage.cs @@ -0,0 +1,129 @@ +// Copyright 2022 DeepL SE (https://www.deepl.com) +// Use of this source code is governed by an MIT +// license that can be found in the LICENSE file. + +using System; +using System.Globalization; +using System.Text.Json.Serialization; + +namespace Nllb.Model +{ + /// + /// A language supported by DeepL translation. The class provides functions to retrieve + /// the available source and target languages. objects are considered equal if their + /// language codes match. + /// + /// + /// + public class Language : IEquatable + { + /// Initializes a new Language object. + /// The language code. + /// The name of the language in English. + //protected Language(string code, string name) + //{ + // Code = DeepL.LanguageCode.Standardize(code); + // Name = name; + //} + + /// Initializes a new Language object. + /// The language code. + /// The name of the language in English. + protected Language(string name) + { + Name = name; + } + + /// The name of the language in English, for example "Italian" or "Romanian". + public string Name { get; } + + /// + /// The language code, for example "it", "ro" or "en-US". Language codes follow ISO 639-1 with an optional + /// regional code from ISO 3166-1. + /// + [JsonPropertyName("language")] + public string Code { get; } + + /// Creates a object corresponding to this language. + public CultureInfo CultureInfo => new CultureInfo(Code); + + /// + /// Returns true if the other object has the same language code, otherwise + /// false. + /// + /// to compare with. + /// true if languages have the same language code, otherwise false. + public bool Equals(Language? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + return Code == other.Code; + } + + /// Converts the language to a string containing the name and language code. + /// A string containing the name and language code of the language. + /// + /// This function is for diagnostic purposes only; the content of the returned string is exempt from backwards + /// compatibility. + /// + public override string ToString() => $"{Name} ({Code})"; + + /// Implicitly cast to string using the language code. + /// object to cast into string. + /// String containing the language code. + public static implicit operator string(Language language) => language.Code; + + /// + /// Determines whether this instance and a specified object, which must also be a object, + /// have the same value. objects are considered equal if their language codes match. + /// + /// The Language to compare to this instance. + /// + /// true if is a and its value is the same as this + /// instance; otherwise, false. If is null, the method + /// returns false. + /// + public override bool Equals(object? obj) => ReferenceEquals(this, obj) || (obj is Language other && Equals(other)); + + /// + /// Returns the hash code for this object, that is simply the hash code of the language + /// code. + /// + /// A 32-bit signed integer hash code. + public override int GetHashCode() => Code.GetHashCode(); + + /// Determines whether two specified Languages have the same value. + /// The first Language to compare, or null. + /// The second Language to compare, or null. + /// + /// true if the value of is the same as the value of ; + /// otherwise, false. + /// + public static bool operator ==(Language? a, Language? b) + { + if ((object?)a == null || (object?)b == null) + { + return Equals(a, b); + } + + return a.Equals(b); + } + + /// Determines whether two specified Languages have different values. + /// The first Language to compare, or null. + /// The second Language to compare, or null. + /// + /// true if the value of is different from the value of , + /// otherwise false. + /// + public static bool operator !=(Language? a, Language? b) => !(a == b); + } +} diff --git a/src/EcTranslators/NllbTranslator/NllbTextResult.cs b/src/EcTranslators/NllbTranslator/NllbTextResult.cs new file mode 100644 index 00000000..cdf65951 --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbTextResult.cs @@ -0,0 +1,39 @@ +// Copyright 2022 DeepL SE (https://www.deepl.com) +// Use of this source code is governed by an MIT +// license that can be found in the LICENSE file. + +using System.Text.Json.Serialization; + +namespace DeepL.Model +{ + /// The result of a text translation. + public sealed class NllbTextResult + { + /// Initializes a new instance of . + /// Translated text. + /// The detected language code of the input text. + /// + /// The constructor for this class (and all other Model classes) should not be used by library users. Ideally it + /// would be marked , but needs to be for JSON deserialization. + /// In future this function may have backwards-incompatible changes. + /// + [JsonConstructor] + public NllbTextResult(string originalText, string translatedText) + { + OriginalText = originalText; + TranslatedText = translatedText; + } + + /// The translated text. + [JsonPropertyName("translatedText")] + public string TranslatedText { get; } + + /// The language code of the source text detected by DeepL. + [JsonPropertyName("originalText")] + public string OriginalText { get; } + + /// Returns the translated text. + /// The translated text. + public override string ToString() => TranslatedText; + } +} diff --git a/src/EcTranslators/NllbTranslator/NllbTranslator.cs b/src/EcTranslators/NllbTranslator/NllbTranslator.cs new file mode 100644 index 00000000..72301b9c --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbTranslator.cs @@ -0,0 +1,309 @@ +// Copyright 2022 DeepL SE (https://www.deepl.com) +// Use of this source code is governed by an MIT +// license that can be found in the LICENSE file. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using DeepL.Internal; +using DeepL.Model; +using static Google.Apis.Requests.BatchRequest; + +namespace Nllb +{ + + public interface ITranslator : IDisposable + { + /// Translate specified text from source language into target language. + /// Text to translate; must not be empty. + /// Language code of the input language, or null to use auto-detection. + /// Language code of the desired output language. + /// influencing translation. + /// The cancellation token to cancel operation. + /// Text translated into specified target language. + /// If any argument is invalid. + /// + /// If any error occurs while communicating with the DeepL API, a + /// or a derived class will be thrown. + /// + Task TranslateTextAsync( + string text, + string? sourceLanguageCode, + string targetLanguageCode, + DeepL.TextTranslateOptions? options = null, + CancellationToken cancellationToken = default); + + /// + /// Client for the DeepL API. To use the DeepL API, initialize an instance of this class using your DeepL + /// Authentication Key. All functions are thread-safe, aside from . + /// + public sealed class Translator : ITranslator + { + /// Base URL for the Nllb accounts. + private const string NllbLServerUrl = "http://localhost:8000"; + + /// Internal class implementing HTTP requests. + private readonly DeepLClient _client; + + /// Initializes a new object using your authentication key. + /// + /// Authentication Key as found in your + ///
DeepL API account. + /// + /// Additional options controlling Translator behaviour. + /// If authKey argument is null. + /// If authKey argument is empty. + /// + /// This function does not establish a connection to the DeepL API. To check connectivity, use + /// . + /// + public Translator(string authKey, DeepL.TranslatorOptions? options = null) + { + options ??= new DeepL.TranslatorOptions(); + + if (authKey == null) + { + throw new ArgumentNullException(nameof(authKey)); + } + + authKey = authKey.Trim(); + + if (authKey.Length == 0) + { + throw new ArgumentException($"{nameof(authKey)} is empty"); + } + + var serverUrl = new Uri(options.ServerUrl ?? NllbLServerUrl); + + var headers = new Dictionary(options.Headers, StringComparer.OrdinalIgnoreCase); + + if (!headers.ContainsKey("User-Agent")) + { + headers.Add("User-Agent", $"deepl-dotnet/{Version()}"); + } + + if (!headers.ContainsKey("Authorization")) + { + headers.Add("Authorization", $"DeepL-Auth-Key {authKey}"); + } + + var clientFactory = options.ClientFactory ?? (() => + DeepLClient.CreateDefaultHttpClient( + options.PerRetryConnectionTimeout, + options.OverallConnectionTimeout, + options.MaximumNetworkRetries)); + + _client = new DeepLClient( + serverUrl, + clientFactory, + headers); + } + + /// Releases the unmanaged resources and disposes of the managed resources used by the . + public void Dispose() => _client.Dispose(); + + /// Retrieves the version string, with format MAJOR.MINOR.BUGFIX. + /// String containing the library version. + public static string Version() + { + var version = Assembly.GetExecutingAssembly().GetCustomAttribute() + ?.InformationalVersion ?? "1.3.0"; + return version; + } + + /// + /// Determines if the given DeepL Authentication Key belongs to an API Free account or an API Pro account. + /// + /// + /// DeepL Authentication Key as found in your + /// DeepL API account. + /// + /// + /// true if the Authentication Key belongs to an API Free account, false if it belongs to an API Pro + /// account. + /// + public static bool AuthKeyIsFreeAccount(string authKey) => true; + + /// + public async Task GetUsageAsync(CancellationToken cancellationToken = default) + { + using var responseMessage = await _client.ApiGetAsync("/api/v1/usage", cancellationToken).ConfigureAwait(false); + await DeepLClient.CheckStatusCodeAsync(responseMessage).ConfigureAwait(false); + var usageFields = await JsonUtils.DeserializeAsync(responseMessage) + .ConfigureAwait(false); + return new Usage(usageFields); + } + + public class TranslateMsg + { + [Newtonsoft.Json.JsonProperty("sourceLanguage")] + public string SourceLanguage { get; set; } + [Newtonsoft.Json.JsonProperty("targetLanguage")] + public string TargetLanguage { get; set; } + [Newtonsoft.Json.JsonProperty("text")] + public string Text { get; set; } + } + + /// + public async Task TranslateTextAsync( + string text, + string? sourceLanguageCode, + string targetLanguageCode, + DeepL.TextTranslateOptions? options = null, + CancellationToken cancellationToken = default) + { + var bodyParams = new TranslateMsg { SourceLanguage = sourceLanguageCode, TargetLanguage = targetLanguageCode, Text = text }; + + using var responseMessage = await _client + .ApiPostJsonAsync("/api/v1/translate", cancellationToken, bodyParams).ConfigureAwait(false); + + // Read response as a string. + var result = await responseMessage.Content.ReadAsStringAsync(); + if (!responseMessage.IsSuccessStatusCode) + throw new ApplicationException(result); + return result; + } + + /// Internal function to retrieve available languages. + /// true to retrieve target languages, false to retrieve source languages. + /// The cancellation token to cancel operation. + /// Array of objects containing information about the available languages. + /// + /// If any error occurs while communicating with the DeepL API, a + /// or a derived class will be thrown. + /// + private async Task GetLanguagesAsync( + CancellationToken cancellationToken = default) + { + using var responseMessage = + await _client.ApiGetAsync("/api/v1/translate/languages", cancellationToken) + .ConfigureAwait(false); + + await DeepLClient.CheckStatusCodeAsync(responseMessage).ConfigureAwait(false); + return await JsonUtils.DeserializeAsync(responseMessage).ConfigureAwait(false); + } + + /// + public async Task GetSupportedLanguagesAsync(CancellationToken cancellationToken = default) => + await GetLanguagesAsync (cancellationToken).ConfigureAwait(false); + + /// + /// Checks the specified languages and options are valid, and returns an enumerable of tuples containing the parameters + /// to include in HTTP request. + /// + /// + /// Language code of translation source language, or null if auto-detection should be + /// used. + /// + /// Language code of translation target language. + /// Extra influencing translation. + /// Enumerable of tuples containing the parameters to include in HTTP request. + /// If the specified languages or options are invalid. + private IEnumerable<(string Key, string Value)> CreateHttpParams( + string? sourceLanguageCode, + string targetLanguageCode, + string text, + DeepL.TextTranslateOptions? options) + { + targetLanguageCode = DeepL.LanguageCode.Standardize(targetLanguageCode); + sourceLanguageCode = sourceLanguageCode == null ? null : DeepL.LanguageCode.Standardize(sourceLanguageCode); + + CheckValidLanguages(sourceLanguageCode, targetLanguageCode); + + var bodyParams = new List<(string Key, string Value)> { ("sourceLanguage", sourceLanguageCode), ("targetLanguage", targetLanguageCode), ("text", text) }; + + return bodyParams; + } + + /// + /// Checks the specified languages and options are valid, and returns an enumerable of tuples containing the parameters + /// to include in HTTP request. + /// + /// + /// Language code of translation source language, or null if auto-detection should be + /// used. + /// + /// Language code of translation target language. + /// Extra influencing translation. + /// Enumerable of tuples containing the parameters to include in HTTP request. + /// If the specified languages or options are invalid. + private IEnumerable<(string Key, string Value)> CreateHttpParams( + string? sourceLanguageCode, + string targetLanguageCode, + DeepL.DocumentTranslateOptions? options) + { + targetLanguageCode = DeepL.LanguageCode.Standardize(targetLanguageCode); + sourceLanguageCode = sourceLanguageCode == null ? null : DeepL.LanguageCode.Standardize(sourceLanguageCode); + + CheckValidLanguages(sourceLanguageCode, targetLanguageCode); + + var bodyParams = new List<(string Key, string Value)> { ("target_lang", targetLanguageCode) }; + if (sourceLanguageCode != null) + { + bodyParams.Add(("source_lang", sourceLanguageCode)); + } + + return bodyParams; + } + + /// Checks the specified source and target language are valid, and throws an exception if not. + /// Language code of translation source language, or null if auto-detection is used. + /// Language code of translation target language. + /// If source or target language code are not valid. + private static void CheckValidLanguages(string? sourceLanguageCode, string targetLanguageCode) + { + if (sourceLanguageCode is { Length: 0 }) + { + throw new ArgumentException($"{nameof(sourceLanguageCode)} must not be empty"); + } + + if (targetLanguageCode.Length == 0) + { + throw new ArgumentException($"{nameof(targetLanguageCode)} must not be empty"); + } + + switch (targetLanguageCode) + { + case "en": + throw new ArgumentException( + $"{nameof(targetLanguageCode)}=\"en\" is deprecated, please use \"en-GB\" or \"en-US\" instead"); + case "pt": + throw new ArgumentException( + $"{nameof(targetLanguageCode)}=\"pt\" is deprecated, please use \"pt-PT\" or \"pt-BR\" instead"); + } + } + + /// + /// Determines recommended time to wait before checking document translation again, using an optional hint of + /// seconds remaining. + /// + /// Optional hint of the number of seconds remaining. + /// to wait. + private static TimeSpan CalculateDocumentWaitTime(int? hintSecondsRemaining) + { + var secs = ((hintSecondsRemaining ?? 0) / 2.0) + 1.0; + secs = Math.Max(1.0, Math.Min(secs, 60.0)); + return TimeSpan.FromSeconds(secs); + } + + /// Class used for JSON-deserialization of text translate results. + private readonly struct TextTranslateResult + { + /// Initializes a new instance of , used for JSON deserialization. + [JsonConstructor] + public TextTranslateResult(NllbTextResult translation) + { + Translation = translation; + } + + /// Array of objects holding text translation results. + public NllbTextResult Translation { get; } + } + } + } +} \ No newline at end of file diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs new file mode 100644 index 00000000..8fd27c0f --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs @@ -0,0 +1,244 @@ +#define DisableBilling + +using System; +using System.Windows.Forms; +using ECInterfaces; // for IEncConverter +using static SilEncConverters40.EcTranslators.NllbTranslator.NllbTranslatorEncConverter; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using SilEncConverters40.EcTranslators.NllbTranslator; +using System.Net; +using Newtonsoft.Json; + +namespace SilEncConverters40.EcTranslators.NllbTranslator +{ + public partial class NllbTranslatorAutoConfigDialog : AutoConfigDialog + { + private readonly ComboBoxItem SourceLanguageNameMustBeConfigured = new ComboBoxItem { Display = "Select Source Language" }; + private readonly ComboBoxItem TargetLanguageNameMustBeConfigured = new ComboBoxItem { Display = "Select Target Language" }; + + // protected List LanguagesSupported; + + public NllbTranslatorAutoConfigDialog + ( + IEncConverters aECs, + string strDisplayName, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strLhsEncodingId, + string strRhsEncodingId, + int lProcessTypeFlags, + bool bIsInRepository + ) + { + Util.DebugWriteLine(this, "(1) BEGIN"); + InitializeComponent(); + Util.DebugWriteLine(this, "initialized component"); + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + + base.Initialize + ( + aECs, + strHtmlFilename, + strDisplayName, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strLhsEncodingId, + strRhsEncodingId, + lProcessTypeFlags, + bIsInRepository + ); + Util.DebugWriteLine(this, "called base.Initalize"); + + var langMap = GetCapabilities().GetAwaiter().GetResult(); + if (langMap == null) + return; + + var languagesSupported = langMap.Select(kvp => new ComboBoxItem { Code = kvp.Key, Display = kvp.Value }) + .OrderBy(c => c.Display) + .ToList(); + InitializeSourceAndTargetLanguages(languagesSupported); + + // if we're editing converter, then set the Converter Spec and say it's unmodified + if (m_bEditMode) + { + System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(ConverterIdentifier)); + + ParseConverterIdentifier(ConverterIdentifier, out string fromLanguage, out string toLanguage); + + var selectedItem = comboBoxSourceLanguages.Items.Cast().FirstOrDefault(l => l.Code == fromLanguage); + comboBoxSourceLanguages.SelectedItem = selectedItem; + comboBoxTargetLanguages.SelectedItem = languagesSupported.FirstOrDefault(l => l.Code == toLanguage); + IsModified = false; + } + else + { + comboBoxSourceLanguages.SelectedItem = SourceLanguageNameMustBeConfigured; + comboBoxTargetLanguages.SelectedItem = TargetLanguageNameMustBeConfigured; + } + + m_bInitialized = true; + + helpProvider.SetHelpString(comboBoxSourceLanguages, Properties.Resources.HelpForNllbTranslatorSourceLanguagesComboBox); + helpProvider.SetHelpString(comboBoxTargetLanguages, Properties.Resources.HelpForNllbTranslatorTargetLanguagesComboBox); + helpProvider.SetHelpString(buttonSetNllbTranslateApiKey, Properties.Resources.HelpForNllbTranslatorAddYourOwnApiKey); + + Util.DebugWriteLine(this, "END"); + } + + public NllbTranslatorAutoConfigDialog + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + Util.DebugWriteLine(this, "(2) BEGIN"); + InitializeComponent(); + + base.Initialize + ( + aECs, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strTestData + ); + Util.DebugWriteLine(this, "END"); + } + + // this method is called either when the user clicks the "Apply" or "OK" buttons *OR* if she + // tries to switch to the Test or Advanced tab. This is the dialog's one opportunity + // to make sure that the user has correctly configured a legitimate converter. + protected override bool OnApply() + { + var selectedToLanguage = (ComboBoxItem)comboBoxTargetLanguages.SelectedItem; + if ((selectedToLanguage == null) || (TargetLanguageNameMustBeConfigured == selectedToLanguage)) + { + MessageBox.Show(this, "The Target Language must be selected!", EncConverters.cstrCaption); + return false; + } + + var selectedFromLanguage = (ComboBoxItem)comboBoxSourceLanguages.SelectedItem; + if ((selectedFromLanguage == null) || (SourceLanguageNameMustBeConfigured == selectedFromLanguage)) + { + MessageBox.Show(this, "The Source Language must be selected!", EncConverters.cstrCaption); + return false; + } + + // for this converter, use the source and target language codes (e.g. hin_Deva) as the converter identifier + ConverterIdentifier = String.Format("{0};{1}", + selectedFromLanguage.Code, + selectedToLanguage.Code); + + return base.OnApply(); + } + + protected override string ProgID + { + get + { + return typeof(NllbTranslatorEncConverter).FullName; + } + } + + protected override string ImplType + { + get + { + return EncConverters.strTypeSILNllbTranslator; + } + } + + protected override string DefaultFriendlyName + { + // as the default, make it the same as the table name (w/o extension) + get + { + var selectedSourceLanguage = (ComboBoxItem)comboBoxSourceLanguages.SelectedItem; + var selectedTargetLanguage = (ComboBoxItem)comboBoxTargetLanguages.SelectedItem; + return $"Nllb Translate {selectedSourceLanguage} to {selectedTargetLanguage}"; + } + } + + /// + /// Initialize the source and possibly target language combo boxes with the translation languages possible. + /// For TranslateWithTransliteration, we only need the source language, so the 'initializeTargetLanguageAlso' parameter should be false + /// + /// true to initialize the target language combo box also + private void InitializeSourceAndTargetLanguages(List languagesSupported) + { + var items = languagesSupported.ToArray(); + comboBoxSourceLanguages.Items.Clear(); + comboBoxSourceLanguages.Items.Add(SourceLanguageNameMustBeConfigured); + comboBoxSourceLanguages.Items.AddRange(items); + + comboBoxTargetLanguages.Items.Clear(); + comboBoxTargetLanguages.Items.Add(TargetLanguageNameMustBeConfigured); + comboBoxTargetLanguages.Items.AddRange(items); + } + + public class ComboBoxItem + { + public string Display { get; set; } + public string Code { get; set; } + public override string ToString() + { + return Display; + } + + public override bool Equals(object obj) + { + if (obj == null) + return false; + var objAsComboBoxItem = obj as ComboBoxItem; + return (objAsComboBoxItem?.Display == Display) || (objAsComboBoxItem?.Code == Code); + } + + public override int GetHashCode() + { + int hashCode = 1075847657; + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Code); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Display); + return hashCode; + } + } + + private void ButtonSetNllbTranslateApiKey_Click(object sender, EventArgs e) + { +#if false +#if encryptingNewCredentials + var nllbTranslatorKeyHide = Properties.Settings.Default.NllbTranslatorCredentials; + var credentials = EncryptionClass.Encrypt(nllbTranslatorKeyHide); +#endif + // only send the key if it's already the override key (so we don't expose ours) + var translatorCredentialsOverride = Properties.Settings.Default.NllbTranslatorKeyOverride; + if (!String.IsNullOrEmpty(translatorCredentialsOverride)) + translatorCredentialsOverride = EncryptionClass.Decrypt(translatorCredentialsOverride); + + using var dlg = new QueryForNllbCredentials(translatorCredentialsOverride); + if (dlg.ShowDialog() == DialogResult.Yes) + { + NllbTranslatorApiKey = dlg.TranslatorKey; + Properties.Settings.Default.Save(); + } +#endif + } + + private void ComboBoxSourceLanguages_SelectedIndexChanged_1(object sender, EventArgs e) + { + IsModified = true; + } + + private void ComboBoxTargetLanguages_SelectedIndexChanged_1(object sender, EventArgs e) + { + IsModified = true; + } + } +} + diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.designer.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.designer.cs new file mode 100644 index 00000000..3ef60e3b --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.designer.cs @@ -0,0 +1,179 @@ +using System; +using ECInterfaces; // for Util + +namespace SilEncConverters40.EcTranslators.NllbTranslator +{ + partial class NllbTranslatorAutoConfigDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.openFileDialogBrowse = new System.Windows.Forms.OpenFileDialog(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelSourceLanguage = new System.Windows.Forms.Label(); + this.labelTargetLanguage = new System.Windows.Forms.Label(); + this.comboBoxSourceLanguages = new System.Windows.Forms.ComboBox(); + this.comboBoxTargetLanguages = new System.Windows.Forms.ComboBox(); + this.buttonSetNllbTranslateApiKey = new System.Windows.Forms.Button(); + this.tabControl.SuspendLayout(); + this.tabPageSetup.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tabPageSetup + // + this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); + // + // buttonApply + // + this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonApply, true); + // + // buttonCancel + // + this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); + this.helpProvider.SetShowHelp(this.buttonCancel, true); + // + // buttonOK + // + this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonOK, true); + // + // buttonSaveInRepository + // + this.helpProvider.SetHelpString(this.buttonSaveInRepository, "\r\nClick to add this converter to the system repository permanently.\r\n "); + this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); + // + // openFileDialogBrowse + // + this.openFileDialogBrowse.DefaultExt = "tec"; + this.openFileDialogBrowse.Filter = "TECkit (compiled) files (*.tec)|*.tec|TECkit (compilable) files (*.map)|*.map"; + this.openFileDialogBrowse.Title = "Browse for TECkit map"; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.labelSourceLanguage, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.labelTargetLanguage, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.comboBoxSourceLanguages, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.comboBoxTargetLanguages, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.buttonSetNllbTranslateApiKey, 1, 3); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); + this.tableLayoutPanel1.TabIndex = 2; + // + // labelSourceLanguage + // + this.labelSourceLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelSourceLanguage.AutoSize = true; + this.labelSourceLanguage.Location = new System.Drawing.Point(3, 18); + this.labelSourceLanguage.Name = "labelSourceLanguage"; + this.labelSourceLanguage.Size = new System.Drawing.Size(91, 13); + this.labelSourceLanguage.TabIndex = 6; + this.labelSourceLanguage.Text = "Source language:"; + // + // labelTargetLanguage + // + this.labelTargetLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelTargetLanguage.AutoSize = true; + this.labelTargetLanguage.Location = new System.Drawing.Point(6, 68); + this.labelTargetLanguage.Name = "labelTargetLanguage"; + this.labelTargetLanguage.Size = new System.Drawing.Size(88, 13); + this.labelTargetLanguage.TabIndex = 8; + this.labelTargetLanguage.Text = "Target language:"; + // + // comboBoxSourceLanguages + // + this.comboBoxSourceLanguages.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.comboBoxSourceLanguages.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxSourceLanguages.FormattingEnabled = true; + this.comboBoxSourceLanguages.Location = new System.Drawing.Point(100, 14); + this.comboBoxSourceLanguages.Name = "comboBoxSourceLanguages"; + this.comboBoxSourceLanguages.Size = new System.Drawing.Size(493, 21); + this.comboBoxSourceLanguages.TabIndex = 7; + this.comboBoxSourceLanguages.SelectedIndexChanged += new System.EventHandler(this.ComboBoxSourceLanguages_SelectedIndexChanged_1); + // + // comboBoxTargetLanguages + // + this.comboBoxTargetLanguages.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.comboBoxTargetLanguages.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxTargetLanguages.FormattingEnabled = true; + this.comboBoxTargetLanguages.Location = new System.Drawing.Point(100, 64); + this.comboBoxTargetLanguages.Name = "comboBoxTargetLanguages"; + this.comboBoxTargetLanguages.Size = new System.Drawing.Size(493, 21); + this.comboBoxTargetLanguages.TabIndex = 9; + this.comboBoxTargetLanguages.SelectedIndexChanged += new System.EventHandler(this.ComboBoxTargetLanguages_SelectedIndexChanged_1); + // + // buttonSetNllbTranslateApiKey + // + this.buttonSetNllbTranslateApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.buttonSetNllbTranslateApiKey.Location = new System.Drawing.Point(100, 368); + this.buttonSetNllbTranslateApiKey.Name = "buttonSetNllbTranslateApiKey"; + this.buttonSetNllbTranslateApiKey.Size = new System.Drawing.Size(294, 23); + this.buttonSetNllbTranslateApiKey.TabIndex = 14; + this.buttonSetNllbTranslateApiKey.Text = "Enter the Nllb Translator Key"; + this.buttonSetNllbTranslateApiKey.UseVisualStyleBackColor = true; + this.buttonSetNllbTranslateApiKey.Visible = false; + this.buttonSetNllbTranslateApiKey.Click += new System.EventHandler(this.ButtonSetNllbTranslateApiKey_Click); + // + // NllbTranslatorAutoConfigDialog + // + this.ClientSize = new System.Drawing.Size(634, 479); + this.Name = "NllbTranslatorAutoConfigDialog"; + this.Controls.SetChildIndex(this.tabControl, 0); + this.Controls.SetChildIndex(this.buttonApply, 0); + this.Controls.SetChildIndex(this.buttonCancel, 0); + this.Controls.SetChildIndex(this.buttonOK, 0); + this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); + this.tabControl.ResumeLayout(false); + this.tabPageSetup.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.OpenFileDialog openFileDialogBrowse; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label labelSourceLanguage; + private System.Windows.Forms.Label labelTargetLanguage; + private System.Windows.Forms.ComboBox comboBoxSourceLanguages; + private System.Windows.Forms.ComboBox comboBoxTargetLanguages; + private System.Windows.Forms.Button buttonSetNllbTranslateApiKey; + } +} diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.resx b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.resx new file mode 100644 index 00000000..f1434d65 --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 17, 17 + + + 341, 17 + + + 450, 17 + + \ No newline at end of file diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs new file mode 100644 index 00000000..146d3736 --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs @@ -0,0 +1,258 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Runtime.InteropServices; // for the class attributes +using System.Text; // for ASCIIEncoding +using System.Threading.Tasks; +using ECInterfaces; // for ConvType +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using static Nllb.ITranslator; +using System.Windows.Forms; + +namespace SilEncConverters40.EcTranslators.NllbTranslator +{ + /// + /// Managed Nllb Translate EncConverter. + /// +#if X64 + [GuidAttribute("DAFFF949-BA9C-4A28-B7A3-13D205D0B838")] +#else + [GuidAttribute("DAFFF949-BA9C-4A28-B7A3-13D205D0B838")] +#endif + // normally these subclasses are treated as the base class (i.e. the + // client can use them orthogonally as IEncConverter interface pointers + // so normally these individual subclasses would be invisible), but if + // we add 'ComVisible = false', then it doesn't get the registry + // 'HKEY_CLASSES_ROOT\SilEncConverters40.EcTranslators.NllbTranslatorEncConverter' which is the basis of + // how it is started (see EncConverters.AddEx). + // [ComVisible(false)] + public class NllbTranslatorEncConverter : TranslatorConverter + { + #region Const Definitions + + public const string CstrDisplayName = "NLLB Translator"; + internal const string strHtmlFilename = "NLLB_Translate_Plug-in_About_box.htm"; + + #endregion Const Definitions + + #region Member Variable Definitions + + + // borrowing from deepL's approach + private static Translator _nllbTranslator; + public static Translator NllbTranslator + { + get + { + if (_nllbTranslator == null) + { + var handler = new DeepLTranslator.Http2CustomHandler(); + var options = new DeepL.TranslatorOptions + { + MaximumNetworkRetries = 2, + PerRetryConnectionTimeout = TimeSpan.FromSeconds(5), + OverallConnectionTimeout = TimeSpan.FromSeconds(10), + ClientFactory = () => new DeepL.HttpClientAndDisposeFlag + { + HttpClient = new HttpClient(handler), + DisposeClient = true, + }, + }; + _nllbTranslator = new Translator(NllbTranslatorApiKey, options); + } + return _nllbTranslator; + } + } + + public static string NllbTranslatorApiKey + { + get + { + var overrideKey = Properties.Settings.Default.NllbTranslatorKeyOverride; + var key = (!String.IsNullOrEmpty(overrideKey)) + ? overrideKey + : Properties.Settings.Default.NllbTranslatorKey; + // var translatorKey = EncryptionClass.Encrypt(key); + return EncryptionClass.Decrypt(key); + } + set + { + var translatorKey = EncryptionClass.Encrypt(value); + Properties.Settings.Default.NllbTranslatorKeyOverride = translatorKey; + } + } + + protected string fromLanguage; + protected string toLanguage; + + #endregion Member Variable Definitions + + #region Initialization + public NllbTranslatorEncConverter() : base(typeof(NllbTranslatorEncConverter).FullName,EncConverters.strTypeSILNllbTranslator) + { + // this is needed to be able to use the NLLB Translator (https call) from Word. If you don't have it, you just get this error: + // Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + } + + public override void Initialize(string converterName, string converterSpec, + ref string lhsEncodingID, ref string rhsEncodingID, ref ConvType conversionType, + ref Int32 processTypeFlags, Int32 codePageInput, Int32 codePageOutput, bool bAdding) + { + Util.DebugWriteLine(this, $"BEGIN: {converterName}, {converterSpec}"); + + // let the base class have first stab at it + base.Initialize(converterName, converterSpec, ref lhsEncodingID, ref rhsEncodingID, + ref conversionType, ref processTypeFlags, codePageInput, codePageOutput, bAdding ); + + if (!ParseConverterIdentifier(converterSpec, out fromLanguage, out toLanguage)) + { + throw new ApplicationException($"{CstrDisplayName} not properly configured! converterName: {converterName}"); + } + + if (conversionType == ConvType.Unknown) + conversionType = ConvType.Unicode_to_Unicode; + + // I'm assuming that we'd have to/want to set up a different one to go the other direction + m_eConversionType = conversionType = MakeUniDirectional(conversionType); + + if (String.IsNullOrEmpty(lhsEncodingID)) + lhsEncodingID = m_strLhsEncodingID = EncConverters.strDefUnicodeEncoding; + if (String.IsNullOrEmpty(rhsEncodingID)) + rhsEncodingID = m_strRhsEncodingID = EncConverters.strDefUnicodeEncoding; + + // this is a Translation process type by definition. This is used by various programs to prevent + // over usage -- e.g. Paratext should be blocking these EncConverter types as the 'Transliteration' + // type project EncConverter (bkz it'll try to "transliterate" the entire corpus -- probably not + // what's wanted). Also ClipboardEncConverter also doesn't process these for a preview (so the + // system tray popup doesn't take forever to display. + processTypeFlags |= (int)ProcessTypeFlags.Translation; + + Util.DebugWriteLine(this, "END"); + } + + internal static bool ParseConverterIdentifier(string converterSpec, + out string fromLanguage, out string toLanguage) + { + toLanguage = null; + + string[] astrs = converterSpec.Split(new[] { ';' }); + + if (astrs.Length < 2) + throw new ApplicationException($"{CstrDisplayName} not properly configured! converterSpec: {converterSpec} must have at least a source and target language (eg. hin_Deva;eng_Latn)"); + + fromLanguage = astrs[0]; + toLanguage = astrs[1]; + return true; + } + +#pragma warning disable CS3002 // Return type is not CLS-compliant + public async static Task> GetCapabilities() +#pragma warning restore CS3002 // Return type is not CLS-compliant + { + try + { + var resultLanguagesSupported = await Task.Run(async delegate + { + return (await NllbTranslator.GetSupportedLanguagesAsync()).ToList(); + }).ConfigureAwait(false); + + var json = LoadEmbeddedResourceFileAsStringExecutingAssembly("NllbHumanReadableLgNames.json"); + var languageCodeMap = JsonConvert.DeserializeObject(json).ToDictionary(l => l.Code, l => l.Name); + + resultLanguagesSupported.Except(languageCodeMap.Select(l => l.Key)) + .ToList() + .ForEach(s => languageCodeMap.Add(s, s)); + return languageCodeMap; + } + catch (Exception ex) + { + var error = LogExceptionMessage($"{typeof(NllbTranslatorEncConverter).Name}.GetCapabilities", ex); + if (error.Contains("Unable to connect to the remote server")) + error += String.Format("{0}{0}Unable to reach the {1} service. Have you turned on the NLLB Docker container?", Environment.NewLine, CstrDisplayName); + MessageBox.Show(error, EncConverters.cstrCaption); + } + return null; + } + + public class LanguageInfo + { + [JsonProperty("Code")] + public string Code { get; set; } + + [JsonProperty("Name")] + public string Name { get; set; } + } + #endregion Initialization + + #region Abstract Base Class Overrides + + [CLSCompliant(false)] + protected override unsafe void DoConvert + ( + byte* lpInBuffer, + int nInLen, + byte* lpOutBuffer, + ref int rnOutLen + ) + { + // we need to put it *back* into a string for the lookup + // [aside: I should probably override base.InternalConvertEx so I can avoid having the base + // class version turn the input string into a byte* for this call just so we can turn around + // and put it *back* into a string for our processing... but I like working with a known + // quantity and no other EncConverter does it that way. Besides, I'm afraid I'll break smtg ;-] + byte[] baIn = new byte[nInLen]; + ECNormalizeData.ByteStarToByteArr(lpInBuffer, nInLen, baIn); + + char[] caIn = Encoding.Unicode.GetChars(baIn); + + // here's our input string + var strInput = new string(caIn); + + var strOutput = String.IsNullOrEmpty(strInput) + ? strInput + : CallNllbTranslator(strInput).Result; + + StringToProperByteStar(strOutput, lpOutBuffer, ref rnOutLen); + } + + private async Task CallNllbTranslator(string strInput) + { + try + { + var translatedText = await Task.Run(async delegate + { + return await NllbTranslator.TranslateTextAsync(strInput, fromLanguage, toLanguage); + }).ConfigureAwait(false); + + var result = HarvestResult(translatedText); + return result; + } + catch (Exception ex) + { + return LogExceptionMessage(GetType().Name, ex); + } + } + + private string HarvestResult(string jsonResult) + { + var json = JValue.Parse(jsonResult); + var output = json.SelectToken("translatedText")?.ToString(); + return output; + } + + #endregion Abstract Base Class Overrides + + #region Misc helpers + + protected override string GetConfigTypeName + { + get { return typeof(NllbTranslatorEncConverterConfig).AssemblyQualifiedName; } + } + + #endregion Misc helpers + } +} diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverterConfig.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverterConfig.cs new file mode 100644 index 00000000..c14e74c7 --- /dev/null +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverterConfig.cs @@ -0,0 +1,64 @@ +using System; +using ECInterfaces; // for IEncConverter + +//uncomment the following line for verbose debugging output using Console.WriteLine +//#define VERBOSE_DEBUGGING + +namespace SilEncConverters40.EcTranslators.NllbTranslator +{ + public class NllbTranslatorEncConverterConfig : EncConverterConfig + { + public NllbTranslatorEncConverterConfig() + : base + ( + typeof(NllbTranslatorEncConverter).FullName, + NllbTranslatorEncConverter.CstrDisplayName, + NllbTranslatorEncConverter.strHtmlFilename, + ProcessTypeFlags.DontKnow + ) + { + } + + [STAThread] + public override bool Configure + ( + IEncConverters aECs, + string strFriendlyName, + ConvType eConversionType, + string strLhsEncodingID, + string strRhsEncodingID + ) + { +#if VERBOSE_DEBUGGING + Console.WriteLine("NllbTranslatorEncConverterConfig(3).Configure BEGIN"); +#endif + NllbTranslatorAutoConfigDialog form = new NllbTranslatorAutoConfigDialog(aECs, m_strDisplayName, m_strFriendlyName, + m_strConverterID, m_eConversionType, m_strLhsEncodingID, m_strRhsEncodingID, + m_lProcessType, m_bIsInRepository); + +#if VERBOSE_DEBUGGING + Console.WriteLine("NllbTranslatorEncConverterConfig.Configure END"); +#endif + return base.Configure(form); + } + + public override void DisplayTestPage + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + Console.Error.WriteLine("NllbTranslatorEncConverterConfig.DisplayTestPage() BEGIN"); + InitializeFromThis(ref strFriendlyName, ref strConverterIdentifier, + ref eConversionType, ref strTestData); + + NllbTranslatorAutoConfigDialog form = new NllbTranslatorAutoConfigDialog(aECs, strFriendlyName, + strConverterIdentifier, eConversionType, strTestData); + + base.DisplayTestPage(form); + } + } +} diff --git a/src/EcTranslators/Properties/Resources.Designer.cs b/src/EcTranslators/Properties/Resources.Designer.cs index a4461dd5..11d3f58f 100644 --- a/src/EcTranslators/Properties/Resources.Designer.cs +++ b/src/EcTranslators/Properties/Resources.Designer.cs @@ -254,7 +254,7 @@ internal static string HelpForGoogleTranslatorAddYourOwnApiKey { } /// - /// Looks up a localized string similar to Choose the language you want to translate or transliterate from. Choose 'Auto-Detect' if you want Google Translate to attempt to determine the input language.. + /// Looks up a localized string similar to Choose the language you want to translate from. Choose 'Auto-Detect' if you want Google Translate to attempt to determine the input language.. /// internal static string HelpForGoogleTranslatorSourceLanguagesComboBox { get { @@ -270,5 +270,32 @@ internal static string HelpForGoogleTranslatorTargetLanguagesComboBox { return ResourceManager.GetString("HelpForGoogleTranslatorTargetLanguagesComboBox", resourceCulture); } } + + /// + /// Looks up a localized string similar to Click this button to enter your own API key.. + /// + internal static string HelpForNllbTranslatorAddYourOwnApiKey { + get { + return ResourceManager.GetString("HelpForNllbTranslatorAddYourOwnApiKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Choose the language you want to translate from.. + /// + internal static string HelpForNllbTranslatorSourceLanguagesComboBox { + get { + return ResourceManager.GetString("HelpForNllbTranslatorSourceLanguagesComboBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Choose the language you want the input text to be translated into.. + /// + internal static string HelpForNllbTranslatorTargetLanguagesComboBox { + get { + return ResourceManager.GetString("HelpForNllbTranslatorTargetLanguagesComboBox", resourceCulture); + } + } } } diff --git a/src/EcTranslators/Properties/Resources.resx b/src/EcTranslators/Properties/Resources.resx index 1f4c9389..8fc6c250 100644 --- a/src/EcTranslators/Properties/Resources.resx +++ b/src/EcTranslators/Properties/Resources.resx @@ -185,9 +185,18 @@ See https://docs.microsoft.com/en-us/azure/cognitive-services/translator/languag Click this button to enter your own Google Cloud credential key. Follow the instructions on the page, https://cloud.google.com/translation-hub/docs/admin-setup, to get create your own Google Cloud Translate service and get your own credentials (e.g. if the default credentials have run out of translation support -- note: the default credentials are using the free pricing tier and is limited to 500K characters/month for all users) - Choose the language you want to translate or transliterate from. Choose 'Auto-Detect' if you want Google Translate to attempt to determine the input language. + Choose the language you want to translate from. Choose 'Auto-Detect' if you want Google Translate to attempt to determine the input language. Choose the language you want the input text to be translated into. + + Click this button to enter your own API key. + + + Choose the language you want to translate from. + + + Choose the language you want the input text to be translated into. +
\ No newline at end of file diff --git a/src/EcTranslators/Properties/Settings.Designer.cs b/src/EcTranslators/Properties/Settings.Designer.cs index 9c411628..d3d66d02 100644 --- a/src/EcTranslators/Properties/Settings.Designer.cs +++ b/src/EcTranslators/Properties/Settings.Designer.cs @@ -250,5 +250,29 @@ public string AzureOpenAiKeyLocationDialogInstructionUrl { this["AzureOpenAiSystemPromptAdditions"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("R2HnnkY7wjy5XeaTWPpfig==")] + public string NllbTranslatorKey { + get { + return ((string)(this["NllbTranslatorKey"])); + } + set { + this["NllbTranslatorKey"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string NllbTranslatorKeyOverride { + get { + return ((string)(this["NllbTranslatorKeyOverride"])); + } + set { + this["NllbTranslatorKeyOverride"] = value; + } + } } } diff --git a/src/EcTranslators/Properties/Settings.settings b/src/EcTranslators/Properties/Settings.settings index 7748d0f5..db3a2417 100644 --- a/src/EcTranslators/Properties/Settings.settings +++ b/src/EcTranslators/Properties/Settings.settings @@ -55,5 +55,11 @@ <string>UseSystemPrompt: Translate from Hindi into English.</string> </ArrayOfString> + + R2HnnkY7wjy5XeaTWPpfig== + + + + \ No newline at end of file diff --git a/src/EcTranslators/TranslatorConverter.cs b/src/EcTranslators/TranslatorConverter.cs index e23e9932..83e8f254 100644 --- a/src/EcTranslators/TranslatorConverter.cs +++ b/src/EcTranslators/TranslatorConverter.cs @@ -1,10 +1,8 @@ using ECInterfaces; using System; -using System.Collections.Generic; +using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; +using System.Reflection; namespace SilEncConverters40.EcTranslators { @@ -39,15 +37,32 @@ internal static unsafe void StringToProperByteStar(string strOutput, byte* lpOut internal static string LogExceptionMessage(string className, Exception ex) { - string msg = "Error occurred: " + ex.Message; + var message = ex.Message; + var msg = "Error occurred: " + message; while (ex.InnerException != null) { ex = ex.InnerException; - msg += $"{Environment.NewLine}because: (InnerException): {ex.Message}"; + if (message.Contains(ex.Message)) + continue; // skip identical msgs + message = ex.Message; + msg += $"{Environment.NewLine}because: (InnerException): {message}"; } Util.DebugWriteLine(className, msg); return msg; } + + public static string LoadEmbeddedResourceFileAsStringExecutingAssembly(string strResourceName) + { + var assembly = Assembly.GetExecutingAssembly(); + strResourceName = assembly.GetManifestResourceNames().FirstOrDefault(n => n.Contains(strResourceName)); + if (string.IsNullOrEmpty(strResourceName)) + return null; + + var resourceAsStream = assembly.GetManifestResourceStream(strResourceName); + StreamReader reader = new StreamReader(resourceAsStream); + string text = reader.ReadToEnd(); + return text; + } } } diff --git a/src/EcTranslators/app.config b/src/EcTranslators/app.config index 8472476d..071cd120 100644 --- a/src/EcTranslators/app.config +++ b/src/EcTranslators/app.config @@ -137,6 +137,12 @@ + + R2HnnkY7wjy5XeaTWPpfig== + + + + \ No newline at end of file diff --git a/src/EncCnvtrs/EncConverters.cs b/src/EncCnvtrs/EncConverters.cs index 91141be2..d0b1c3ce 100755 --- a/src/EncCnvtrs/EncConverters.cs +++ b/src/EncCnvtrs/EncConverters.cs @@ -87,8 +87,9 @@ public class EncConverters : Hashtable, IEncConverters public const string strTypeSILGoogleTranslator = "SIL.GoogleTranslator"; public const string strTypeSILDeepLTranslator = "SIL.DeepLTranslator"; public const string strTypeSILAzureOpenAiTranslator = "SIL.AzureOpenAI"; + public const string strTypeSILNllbTranslator = "SIL.NllbTranslator"; - public const string cstrTempConverterPrefix = "Temporary Converter"; + public const string cstrTempConverterPrefix = "Temporary Converter"; // default values for XML file attributes public const string HKLM_PATH_TO_XML_FILE = @"SOFTWARE\SIL\EncodingConverterRepository"; diff --git a/src/TestEncCnvtrs/TestEcTranslators.cs b/src/TestEncCnvtrs/TestEcTranslators.cs index b7e85ba3..249068a4 100644 --- a/src/TestEncCnvtrs/TestEcTranslators.cs +++ b/src/TestEncCnvtrs/TestEcTranslators.cs @@ -13,6 +13,7 @@ using SilEncConverters40.EcTranslators.DeepLTranslator; using SilEncConverters40.EcTranslators.GoogleTranslator; using SilEncConverters40.EcTranslators.AzureOpenAI; +using SilEncConverters40.EcTranslators.NllbTranslator; using System.Threading.Tasks; namespace TestEncCnvtrs @@ -198,7 +199,32 @@ public void CleanupForClass() m_repoFile = null; } - private const string AzureOpenAIConverterFriendlyName = "ChatGptTranslator"; + private const string NllbConverterFriendlyName = "NllbTranslator"; + + /// + /// To run this test, you need to have the https://github.com/Nateowami/NLLB-demo repo clones, + /// and built into a docker container and running on your local machine + /// + /// + /// + /// + [Test] + [TestCase("hin_Deva;eng_Latn", + "वे जानते हैं कि परमेश्वर का अस्तित्व है और यह सब कुछ उनके लिए ही बनाया है। परंतु फिर भी न तो वे परमेश्वर का कोई सम्‍मान, और न ही तो उसका धन्यवाद करते हैं। इसलिए उनकी आँखें में पर्दा पड़ गया है, और परमेश्वर के विषय में उनका जो विचार है, वह गलत हो चुका है।", + "They know that God exists and that everything was made for them. Yet they do not give glory to God or give him thanks. Their minds are blinded and their thoughts are in error.")] + public void TestNllbConverter(string converterSpec, string testInput, string testOutput) + { + m_encConverters.AddConversionMap(NllbConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, + EncConverters.strTypeSILNllbTranslator, "UNICODE", "UNICODE", ProcessTypeFlags.Translation); + + var theEc = m_encConverters[NllbConverterFriendlyName]; + + // do a forward conversion + var strOutput = theEc.Convert(testInput); + Assert.AreEqual(testOutput, strOutput); + } + + private const string AzureOpenAIConverterFriendlyName = "ChatGptTranslator"; [Test] [TestCase("Hindi;English;Translate from Hindi into English.", "यीशु ने यह भी कहा,", "Jesus also said this,")] From 304858a53d7e0a16b46d47a3d6a56fceccbce830 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 18:59:55 -0500 Subject: [PATCH 019/113] removed obsolete solutions to fix GHA build --- EncConverters 2015.sln | 1477 ---------------------------------------- EncConverters-mono.sln | 666 ------------------ 2 files changed, 2143 deletions(-) delete mode 100644 EncConverters 2015.sln delete mode 100644 EncConverters-mono.sln diff --git a/EncConverters 2015.sln b/EncConverters 2015.sln deleted file mode 100644 index 483f143c..00000000 --- a/EncConverters 2015.sln +++ /dev/null @@ -1,1477 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.1000 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECInterfaces 2010", "src\ECInterfaces\ECInterfaces 2010.csproj", "{2935E02F-43ED-4670-9A00-A91B0AD3D66C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EncCnvtrs 2010", "src\EncCnvtrs\EncCnvtrs 2010.csproj", "{3E4B908A-4F96-43C5-981B-1AA4B73CCC26}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECFileConverter 2010", "src\ECFileConverter\ECFileConverter 2010.csproj", "{1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIGuesserEC 2010", "src\AIGuesserEC\AIGuesserEC 2010.csproj", "{B718B5F3-A49A-454C-84FD-6D6F59EC7410}" - ProjectSection(ProjectDependencies) = postProject - {2E70A627-605F-4625-8637-A7109DB8B35C} = {2E70A627-605F-4625-8637-A7109DB8B35C} - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DriveAiEncConverter 2010", "src\DriveAiEncConverter\DriveAiEncConverter 2010.csproj", "{088E2974-9588-4EDA-AF7F-869A10DF402A}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - {B718B5F3-A49A-454C-84FD-6D6F59EC7410} = {B718B5F3-A49A-454C-84FD-6D6F59EC7410} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilIndicEncConverters 2010", "src\SilIndicEncConverters\SilIndicEncConverters 2010.csproj", "{DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ECDriver", "src\ECDriver\windows\ECDriver 2010.vcxproj", "{1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IcuConvEC", "src\IcuEC\IcuConvEC 2010.vcxproj", "{B6F84043-658E-4732-AFCA-BBE07FF465CB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IcuRegexEC", "src\IcuEC\IcuRegexEC 2010.vcxproj", "{F77C7224-DF82-4ADF-A761-773D21B58EF4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IcuTranslitEC", "src\IcuEC\IcuTranslitEC 2010.vcxproj", "{1D0DA000-6192-4B57-A377-7A0A5AB1A121}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IcuEC 2010", "src\IcuEC\IcuEC 2010.csproj", "{D1BAE593-A552-4F1A-8B08-5A1C27875C2F}" - ProjectSection(ProjectDependencies) = postProject - {1D0DA000-6192-4B57-A377-7A0A5AB1A121} = {1D0DA000-6192-4B57-A377-7A0A5AB1A121} - {F77C7224-DF82-4ADF-A761-773D21B58EF4} = {F77C7224-DF82-4ADF-A761-773D21B58EF4} - {B6F84043-658E-4732-AFCA-BBE07FF465CB} = {B6F84043-658E-4732-AFCA-BBE07FF465CB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PyScriptEncConverter", "src\PyScriptEC\PyScriptEncConverter 2010.vcxproj", "{C5808AC0-A52F-4D77-9903-AE6709712B62}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PyScriptEC 2010", "src\PyScriptEC\PyScriptEC 2010.csproj", "{0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}" - ProjectSection(ProjectDependencies) = postProject - {C5808AC0-A52F-4D77-9903-AE6709712B62} = {C5808AC0-A52F-4D77-9903-AE6709712B62} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerlExpressionEC 2010", "src\PerlExpressionEC\PerlExpressionEC 2010.csproj", "{4704F67B-246D-483C-B840-231F42D7A12B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CcEC 2010", "src\CcEC\CcEC 2010.csproj", "{2E70A627-605F-4625-8637-A7109DB8B35C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestEncCnvtrs 2010", "src\TestEncCnvtrs\TestEncCnvtrs 2010.csproj", "{E13305E0-0AC9-4181-A9AD-3B9B0A479087}" - ProjectSection(ProjectDependencies) = postProject - {1D0DA000-6192-4B57-A377-7A0A5AB1A121} = {1D0DA000-6192-4B57-A377-7A0A5AB1A121} - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9} = {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9} - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} = {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} - {F77C7224-DF82-4ADF-A761-773D21B58EF4} = {F77C7224-DF82-4ADF-A761-773D21B58EF4} - {2E70A627-605F-4625-8637-A7109DB8B35C} = {2E70A627-605F-4625-8637-A7109DB8B35C} - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {B6F84043-658E-4732-AFCA-BBE07FF465CB} = {B6F84043-658E-4732-AFCA-BBE07FF465CB} - {088E2974-9588-4EDA-AF7F-869A10DF402A} = {088E2974-9588-4EDA-AF7F-869A10DF402A} - {4704F67B-246D-483C-B840-231F42D7A12B} = {4704F67B-246D-483C-B840-231F42D7A12B} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F} = {D1BAE593-A552-4F1A-8B08-5A1C27875C2F} - {C5808AC0-A52F-4D77-9903-AE6709712B62} = {C5808AC0-A52F-4D77-9903-AE6709712B62} - {B718B5F3-A49A-454C-84FD-6D6F59EC7410} = {B718B5F3-A49A-454C-84FD-6D6F59EC7410} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppDataMover", "src\AppDataMover\AppDataMover.csproj", "{AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}" - ProjectSection(ProjectDependencies) = postProject - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GuesserEC", "src\AIGuesserEC\GuesserEC\GuesserEC.vcxproj", "{7F906C15-8DCD-466E-9AF3-2EF50E7FC046}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "EC_40_MM", "installer\EC_40_MM\EC_40_MM.wixproj", "{DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9} = {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9} - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC} = {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "CcDLLsMM", "installer\CcDLLsMM\CcDLLsMM.wixproj", "{69904B85-6945-4369-A2E3-79DD7319FB53}" - ProjectSection(ProjectDependencies) = postProject - {2E70A627-605F-4625-8637-A7109DB8B35C} = {2E70A627-605F-4625-8637-A7109DB8B35C} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "AIGuesserMM", "installer\AIGuesserMM\AIGuesserMM.wixproj", "{406EA033-1918-4CE2-AE3D-1AC9B14CF111}" - ProjectSection(ProjectDependencies) = postProject - {B718B5F3-A49A-454C-84FD-6D6F59EC7410} = {B718B5F3-A49A-454C-84FD-6D6F59EC7410} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "TECkitDLLsMM", "installer\TECkitDLLsMM\TECkitDLLsMM.wixproj", "{6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Installer", "Installer", "{D3355CC9-A400-49B7-ADCE-F623A816D1B5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Testing", "Testing", "{652EFEB5-5F0A-4578-A518-D77FEDB0A53C}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PerlEcMM", "installer\PerlEcMM\PerlEcMM.wixproj", "{D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}" - ProjectSection(ProjectDependencies) = postProject - {4704F67B-246D-483C-B840-231F42D7A12B} = {4704F67B-246D-483C-B840-231F42D7A12B} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PythonEcMM", "installer\PythonEcMM\PythonEcMM.wixproj", "{34D26D24-57AF-4031-B5B6-5A8C9279AFCC}" - ProjectSection(ProjectDependencies) = postProject - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} = {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "TECkit64bitDllsMM", "installer\TECkit64bitDllsMM\TECkit64bitDllsMM.wixproj", "{AE5F8D43-08DE-4E3B-AE84-E89A01122B40}" -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PythonEc64bitMM", "installer\PythonEc64bitMM\PythonEc64bitMM.wixproj", "{CCBB5714-9635-4C54-AE1C-4D06441B9F3A}" - ProjectSection(ProjectDependencies) = postProject - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} = {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} - {C5808AC0-A52F-4D77-9903-AE6709712B62} = {C5808AC0-A52F-4D77-9903-AE6709712B62} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PerlEc64bitMM", "installer\PerlEc64bitMM\PerlEc64bitMM.wixproj", "{25E133DF-507B-422A-91FD-4E36155ABF7A}" - ProjectSection(ProjectDependencies) = postProject - {4704F67B-246D-483C-B840-231F42D7A12B} = {4704F67B-246D-483C-B840-231F42D7A12B} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "EC_40_64bit_MM", "installer\EC_40_64bit_MM\EC_40_64bit_MM.wixproj", "{4BF6846B-4DB1-4C91-9435-43E1077BEEE4}" - ProjectSection(ProjectDependencies) = postProject - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9} = {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9} - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC} = {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC} - EndProjectSection -EndProject -Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "CcDLLs64bitMM", "installer\CcDLLs64bitMM\CcDLLs64bitMM.wixproj", "{8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}" - ProjectSection(ProjectDependencies) = postProject - {2E70A627-605F-4625-8637-A7109DB8B35C} = {2E70A627-605F-4625-8637-A7109DB8B35C} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - LegacyDebug|Any CPU = LegacyDebug|Any CPU - LegacyDebug|Mixed Platforms = LegacyDebug|Mixed Platforms - LegacyDebug|Win32 = LegacyDebug|Win32 - LegacyDebug|x64 = LegacyDebug|x64 - LegacyDebug|x86 = LegacyDebug|x86 - LegacyRelease|Any CPU = LegacyRelease|Any CPU - LegacyRelease|Mixed Platforms = LegacyRelease|Mixed Platforms - LegacyRelease|Win32 = LegacyRelease|Win32 - LegacyRelease|x64 = LegacyRelease|x64 - LegacyRelease|x86 = LegacyRelease|x86 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - Template|Any CPU = Template|Any CPU - Template|Mixed Platforms = Template|Mixed Platforms - Template|Win32 = Template|Win32 - Template|x64 = Template|x64 - Template|x86 = Template|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Win32.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|x64.ActiveCfg = Debug|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|x64.Build.0 = Debug|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|x86.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|x86.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|x64.Build.0 = Debug|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|x64.ActiveCfg = Release|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|x64.Build.0 = Release|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|x86.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Any CPU.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Win32.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Win32.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|x64.ActiveCfg = Release|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|x64.Build.0 = Release|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|x86.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|x86.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Any CPU.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Any CPU.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Win32.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Win32.Build.0 = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|x64.ActiveCfg = Release|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|x64.Build.0 = Release|x64 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|x86.ActiveCfg = Release|Any CPU - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|x86.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Win32.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Win32.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|x64.ActiveCfg = Debug|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|x64.Build.0 = Debug|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|x86.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|x86.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|x64.Build.0 = Debug|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|x64.ActiveCfg = Release|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|x64.Build.0 = Release|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|x86.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Any CPU.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Win32.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Win32.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|x64.ActiveCfg = Release|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|x64.Build.0 = Release|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|x86.ActiveCfg = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|x86.Build.0 = Release|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Any CPU.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Any CPU.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Mixed Platforms.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Mixed Platforms.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Win32.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Win32.Build.0 = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|x64.ActiveCfg = Debug|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|x64.Build.0 = Debug|x64 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|x86.ActiveCfg = Debug|Any CPU - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|x86.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Win32.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Win32.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|x64.ActiveCfg = Debug|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|x64.Build.0 = Debug|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|x86.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|x86.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|x64.Build.0 = Debug|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|x64.ActiveCfg = Release|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|x64.Build.0 = Release|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|x86.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Any CPU.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Win32.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Win32.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|x64.ActiveCfg = Release|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|x64.Build.0 = Release|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|x86.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|x86.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Any CPU.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Any CPU.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Win32.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Win32.Build.0 = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|x64.ActiveCfg = Release|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|x64.Build.0 = Release|x64 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|x86.ActiveCfg = Release|Any CPU - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|x86.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Win32.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Win32.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|x64.ActiveCfg = Debug|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|x64.Build.0 = Debug|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|x86.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|x86.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|x64.Build.0 = Debug|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|x64.ActiveCfg = Release|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|x64.Build.0 = Release|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|x86.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Any CPU.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Win32.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Win32.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|x64.ActiveCfg = Release|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|x64.Build.0 = Release|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|x86.ActiveCfg = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|x86.Build.0 = Release|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Any CPU.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Any CPU.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Mixed Platforms.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Mixed Platforms.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Win32.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Win32.Build.0 = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|x64.ActiveCfg = Debug|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|x64.Build.0 = Debug|x64 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|x86.ActiveCfg = Debug|Any CPU - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|x86.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Win32.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Win32.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|x64.ActiveCfg = Debug|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|x64.Build.0 = Debug|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|x86.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|x86.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|x64.Build.0 = Debug|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|x64.ActiveCfg = Release|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|x64.Build.0 = Release|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|x86.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Any CPU.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Win32.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Win32.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|x64.ActiveCfg = Release|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|x64.Build.0 = Release|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|x86.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|x86.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Any CPU.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Any CPU.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Win32.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Win32.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|x64.ActiveCfg = Release|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|x64.Build.0 = Release|x64 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|x86.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|x86.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Win32.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Win32.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|x64.ActiveCfg = Debug|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|x64.Build.0 = Debug|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|x86.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|x86.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|x64.Build.0 = Debug|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|x64.ActiveCfg = Release|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|x64.Build.0 = Release|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|x86.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Any CPU.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Win32.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Win32.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|x64.ActiveCfg = Release|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|x64.Build.0 = Release|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|x86.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|x86.Build.0 = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Any CPU.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Any CPU.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Mixed Platforms.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Mixed Platforms.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Win32.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Win32.Build.0 = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|x64.ActiveCfg = Debug|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|x64.Build.0 = Debug|x64 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|x86.ActiveCfg = Debug|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|x86.Build.0 = Debug|Any CPU - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Win32.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Win32.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|x64.ActiveCfg = Debug|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|x64.Build.0 = Debug|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|x86.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|x86.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|x64.Build.0 = Debug|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Win32.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|x64.ActiveCfg = Release|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|x64.Build.0 = Release|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Any CPU.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Mixed Platforms.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Win32.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Win32.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|x64.ActiveCfg = Release|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|x64.Build.0 = Release|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|x86.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|x86.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Any CPU.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Mixed Platforms.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Win32.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Win32.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|x64.ActiveCfg = Release|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|x64.Build.0 = Release|x64 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|x86.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Win32.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Win32.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|x64.ActiveCfg = Debug|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|x64.Build.0 = Debug|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|x86.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|x86.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|x64.Build.0 = Debug|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Win32.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|x64.ActiveCfg = Release|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|x64.Build.0 = Release|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Any CPU.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Mixed Platforms.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Win32.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Win32.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|x64.ActiveCfg = Release|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|x64.Build.0 = Release|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|x86.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|x86.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Any CPU.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Mixed Platforms.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Win32.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Win32.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|x64.ActiveCfg = Release|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|x64.Build.0 = Release|x64 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|x86.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Win32.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Win32.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|x64.ActiveCfg = Debug|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|x64.Build.0 = Debug|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|x86.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|x86.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|x64.Build.0 = Debug|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Win32.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|x64.ActiveCfg = Release|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|x64.Build.0 = Release|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Any CPU.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Mixed Platforms.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Win32.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Win32.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|x64.ActiveCfg = Release|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|x64.Build.0 = Release|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|x86.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|x86.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Any CPU.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Mixed Platforms.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Win32.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Win32.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|x64.ActiveCfg = Release|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|x64.Build.0 = Release|x64 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|x86.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Win32.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Win32.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|x64.ActiveCfg = Debug|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|x64.Build.0 = Debug|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|x86.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|x86.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|x64.Build.0 = Debug|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Win32.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|x64.ActiveCfg = Release|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|x64.Build.0 = Release|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Any CPU.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Mixed Platforms.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Win32.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Win32.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|x64.ActiveCfg = Release|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|x64.Build.0 = Release|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|x86.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|x86.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Any CPU.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Mixed Platforms.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Win32.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Win32.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|x64.ActiveCfg = Release|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|x64.Build.0 = Release|x64 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|x86.ActiveCfg = Release|Win32 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Win32.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Win32.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|x64.ActiveCfg = Debug|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|x64.Build.0 = Debug|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|x86.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|x86.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|x64.Build.0 = Debug|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|x64.ActiveCfg = Release|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|x64.Build.0 = Release|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|x86.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Any CPU.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Win32.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Win32.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|x64.ActiveCfg = Release|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|x64.Build.0 = Release|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|x86.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|x86.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Any CPU.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Any CPU.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Win32.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Win32.Build.0 = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|x64.ActiveCfg = Release|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|x64.Build.0 = Release|x64 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|x86.ActiveCfg = Release|Any CPU - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|x86.Build.0 = Release|Any CPU - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Win32.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Win32.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|x64.ActiveCfg = Debug|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|x64.Build.0 = Debug|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|x86.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|x86.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|x64.Build.0 = Debug|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Win32.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|x64.ActiveCfg = Release|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|x64.Build.0 = Release|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Any CPU.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Win32.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Win32.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|x64.ActiveCfg = Release|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|x64.Build.0 = Release|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|x86.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|x86.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Any CPU.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Mixed Platforms.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Win32.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Win32.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|x64.ActiveCfg = Release|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|x64.Build.0 = Release|x64 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|x86.ActiveCfg = Release|Win32 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Win32.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Win32.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|x64.ActiveCfg = Debug|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|x64.Build.0 = Debug|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|x86.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|x86.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|x64.Build.0 = Debug|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|x64.ActiveCfg = Release|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|x64.Build.0 = Release|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|x86.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Any CPU.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Win32.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Win32.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|x64.ActiveCfg = Release|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|x64.Build.0 = Release|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|x86.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|x86.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Any CPU.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Any CPU.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Win32.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Win32.Build.0 = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|x64.ActiveCfg = Release|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|x64.Build.0 = Release|x64 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|x86.ActiveCfg = Release|Any CPU - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|x86.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Win32.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Win32.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|x64.ActiveCfg = Debug|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|x64.Build.0 = Debug|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|x86.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|x86.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|x64.Build.0 = Debug|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|x64.ActiveCfg = Release|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|x64.Build.0 = Release|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|x86.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Any CPU.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Win32.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Win32.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|x64.ActiveCfg = Release|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|x64.Build.0 = Release|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|x86.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|x86.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Any CPU.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Any CPU.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Win32.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Win32.Build.0 = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|x64.ActiveCfg = Release|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|x64.Build.0 = Release|x64 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|x86.ActiveCfg = Release|Any CPU - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|x86.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Win32.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|x64.ActiveCfg = Debug|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|x64.Build.0 = Debug|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|x86.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|x86.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|x64.Build.0 = Debug|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|x64.ActiveCfg = Release|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|x64.Build.0 = Release|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|x86.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Any CPU.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Win32.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Win32.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|x64.ActiveCfg = Release|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|x64.Build.0 = Release|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|x86.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|x86.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Any CPU.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Any CPU.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Win32.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Win32.Build.0 = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|x64.ActiveCfg = Release|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|x64.Build.0 = Release|x64 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|x86.ActiveCfg = Release|Any CPU - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|x86.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Win32.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Win32.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|x64.ActiveCfg = Debug|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|x64.Build.0 = Debug|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|x86.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|x86.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|x64.Build.0 = Debug|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|x64.ActiveCfg = Release|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|x64.Build.0 = Release|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|x86.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Any CPU.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Win32.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Win32.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|x64.ActiveCfg = Release|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|x64.Build.0 = Release|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|x86.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|x86.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Any CPU.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Any CPU.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Win32.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Win32.Build.0 = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|x64.ActiveCfg = Release|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|x64.Build.0 = Release|x64 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|x86.ActiveCfg = Release|Any CPU - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|x86.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Win32.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Win32.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|x64.ActiveCfg = Debug|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|x64.Build.0 = Debug|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|x86.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|x86.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Win32.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|x64.Build.0 = Debug|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|x86.ActiveCfg = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|x86.Build.0 = Debug|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Win32.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|x64.ActiveCfg = Release|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|x64.Build.0 = Release|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|x86.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|x86.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Any CPU.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Win32.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Win32.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|x64.ActiveCfg = Release|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|x64.Build.0 = Release|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|x86.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|x86.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Any CPU.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Any CPU.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Win32.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Win32.Build.0 = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|x64.ActiveCfg = Release|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|x64.Build.0 = Release|x64 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|x86.ActiveCfg = Release|Any CPU - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|x86.Build.0 = Release|Any CPU - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Win32.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Win32.Build.0 = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|x64.ActiveCfg = Debug|x64 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|x86.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|x86.Build.0 = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Any CPU.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Mixed Platforms.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Mixed Platforms.Build.0 = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Win32.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Win32.Build.0 = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|x64.ActiveCfg = LegacyDebug|x64 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|x86.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Any CPU.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Mixed Platforms.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Mixed Platforms.Build.0 = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Win32.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Win32.Build.0 = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|x64.ActiveCfg = LegacyRelease|x64 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|x86.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Any CPU.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Mixed Platforms.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Win32.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Win32.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|x64.ActiveCfg = Release|x64 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|x86.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|x86.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Any CPU.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Mixed Platforms.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Win32.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Win32.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|x64.ActiveCfg = Release|x64 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|x64.Build.0 = Release|x64 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|x86.ActiveCfg = Release|Win32 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Debug|Any CPU.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Debug|Win32.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Debug|x64.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Debug|x86.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|x64.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|x64.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyDebug|x86.Build.0 = Debug|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|x64.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|x64.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|x86.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.LegacyRelease|x86.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|Any CPU.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|Mixed Platforms.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|Win32.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|Win32.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|x64.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|x86.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Release|x86.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|Any CPU.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|Mixed Platforms.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|Win32.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|x64.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|x64.Build.0 = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|x86.ActiveCfg = Release|x86 - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014}.Template|x86.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Debug|Any CPU.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Debug|Win32.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Debug|x64.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Debug|x86.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|x64.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|x64.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyDebug|x86.Build.0 = Debug|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|x64.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|x64.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|x86.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.LegacyRelease|x86.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|Any CPU.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|Mixed Platforms.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|Win32.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|Win32.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|x64.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|x86.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Release|x86.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|Any CPU.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|Mixed Platforms.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|Win32.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|x64.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|x64.Build.0 = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|x86.ActiveCfg = Release|x86 - {69904B85-6945-4369-A2E3-79DD7319FB53}.Template|x86.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Debug|Any CPU.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Debug|Win32.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Debug|x64.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Debug|x86.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|x64.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|x64.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyDebug|x86.Build.0 = Debug|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|x64.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|x64.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|x86.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.LegacyRelease|x86.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|Any CPU.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|Mixed Platforms.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|Win32.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|Win32.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|x64.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|x86.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Release|x86.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|Any CPU.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|Mixed Platforms.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|Win32.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|x64.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|x64.Build.0 = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|x86.ActiveCfg = Release|x86 - {406EA033-1918-4CE2-AE3D-1AC9B14CF111}.Template|x86.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Debug|Any CPU.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Debug|Win32.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Debug|x64.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Debug|x86.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|x64.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|x64.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyDebug|x86.Build.0 = Debug|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|x64.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|x64.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|x86.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.LegacyRelease|x86.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|Any CPU.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|Mixed Platforms.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|Win32.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|Win32.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|x64.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|x86.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Release|x86.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|Any CPU.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|Mixed Platforms.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|Win32.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|x64.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|x64.Build.0 = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|x86.ActiveCfg = Release|x86 - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF}.Template|x86.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Debug|Any CPU.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Debug|Win32.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Debug|x64.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Debug|x86.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|x64.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|x64.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyDebug|x86.Build.0 = Debug|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|x64.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|x64.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|x86.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.LegacyRelease|x86.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|Any CPU.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|Mixed Platforms.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|Win32.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|Win32.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|x64.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|x86.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Release|x86.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|Any CPU.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|Mixed Platforms.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|Win32.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|x64.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|x64.Build.0 = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|x86.ActiveCfg = Release|x86 - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E}.Template|x86.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Debug|Any CPU.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Debug|Win32.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Debug|x64.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Debug|x86.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|x64.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|x64.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyDebug|x86.Build.0 = Debug|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|x64.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|x64.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|x86.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.LegacyRelease|x86.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|Any CPU.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|Mixed Platforms.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|Win32.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|Win32.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|x64.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|x86.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Release|x86.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|Any CPU.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|Mixed Platforms.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|Win32.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|x64.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|x64.Build.0 = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|x86.ActiveCfg = Release|x86 - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC}.Template|x86.Build.0 = Release|x86 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Debug|Any CPU.ActiveCfg = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Debug|Win32.ActiveCfg = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Debug|x64.ActiveCfg = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Debug|x86.ActiveCfg = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|Any CPU.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|Any CPU.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|Win32.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|Win32.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|x64.Build.0 = Debug|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|x86.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyDebug|x86.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|Any CPU.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|Any CPU.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|Mixed Platforms.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|Win32.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|Win32.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|x64.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|x64.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|x86.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.LegacyRelease|x86.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Release|Any CPU.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Release|Win32.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Release|x64.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Release|x64.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Release|x86.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|Any CPU.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|Any CPU.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|Mixed Platforms.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|Mixed Platforms.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|Win32.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|Win32.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|x64.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|x64.Build.0 = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|x86.ActiveCfg = Release|x64 - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40}.Template|x86.Build.0 = Release|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Debug|Any CPU.ActiveCfg = Debug|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Debug|Win32.ActiveCfg = Debug|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Debug|x64.ActiveCfg = Debug|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Debug|x86.ActiveCfg = Debug|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|Any CPU.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|Any CPU.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|Win32.Build.0 = Debug|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|x64.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|x64.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyDebug|x86.Build.0 = Debug|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|Any CPU.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|Win32.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|x64.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|x64.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|x86.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.LegacyRelease|x86.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Release|Any CPU.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Release|Win32.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Release|x64.ActiveCfg = Release|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Release|x64.Build.0 = Release|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Release|x86.ActiveCfg = Release|x64 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|Any CPU.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|Any CPU.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|Mixed Platforms.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|Win32.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|Win32.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|x64.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|x64.Build.0 = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|x86.ActiveCfg = Release|x86 - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A}.Template|x86.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Debug|Any CPU.ActiveCfg = Debug|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Debug|Win32.ActiveCfg = Debug|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Debug|x64.ActiveCfg = Debug|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Debug|x86.ActiveCfg = Debug|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|Any CPU.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|Any CPU.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|Win32.Build.0 = Debug|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|x64.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|x64.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyDebug|x86.Build.0 = Debug|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|Any CPU.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|Win32.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|x64.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|x64.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|x86.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.LegacyRelease|x86.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Release|Any CPU.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Release|Win32.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Release|x64.ActiveCfg = Release|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Release|x64.Build.0 = Release|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Release|x86.ActiveCfg = Release|x64 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|Any CPU.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|Any CPU.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|Mixed Platforms.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|Win32.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|Win32.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|x64.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|x64.Build.0 = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|x86.ActiveCfg = Release|x86 - {25E133DF-507B-422A-91FD-4E36155ABF7A}.Template|x86.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Debug|Any CPU.ActiveCfg = Debug|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Debug|Win32.ActiveCfg = Debug|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Debug|x64.ActiveCfg = Debug|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Debug|x86.ActiveCfg = Debug|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|Any CPU.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|Any CPU.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|Win32.Build.0 = Debug|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|x64.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|x64.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyDebug|x86.Build.0 = Debug|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|Any CPU.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|Win32.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|x64.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|x64.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|x86.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.LegacyRelease|x86.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Release|Any CPU.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Release|Win32.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Release|x64.ActiveCfg = Release|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Release|x64.Build.0 = Release|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Release|x86.ActiveCfg = Release|x64 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Any CPU.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Any CPU.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Mixed Platforms.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Win32.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Win32.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x64.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x64.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x86.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x86.Build.0 = Release|x86 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Debug|Any CPU.ActiveCfg = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Debug|Win32.ActiveCfg = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Debug|x64.ActiveCfg = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Debug|x86.ActiveCfg = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|Any CPU.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|Any CPU.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|Win32.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|Win32.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|x64.ActiveCfg = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|x64.Build.0 = Debug|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|x86.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyDebug|x86.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|Any CPU.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|Any CPU.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|Mixed Platforms.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|Win32.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|Win32.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|x64.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|x64.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|x86.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.LegacyRelease|x86.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Release|Any CPU.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Release|Win32.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Release|x64.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Release|x64.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Release|x86.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|Any CPU.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|Any CPU.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|Mixed Platforms.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|Mixed Platforms.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|Win32.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|Win32.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|x64.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|x64.Build.0 = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|x86.ActiveCfg = Release|x64 - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Template|x86.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {088E2974-9588-4EDA-AF7F-869A10DF402A} = {652EFEB5-5F0A-4578-A518-D77FEDB0A53C} - {DBF25A0C-5F5B-4060-AC5C-CDC50C4AA014} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {69904B85-6945-4369-A2E3-79DD7319FB53} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {406EA033-1918-4CE2-AE3D-1AC9B14CF111} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {6EAFDB48-2E2C-4874-9924-2D8B115FA1EF} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {D6A6243C-A7F4-4174-80C5-5EFD39C29D5E} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {34D26D24-57AF-4031-B5B6-5A8C9279AFCC} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {AE5F8D43-08DE-4E3B-AE84-E89A01122B40} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {CCBB5714-9635-4C54-AE1C-4D06441B9F3A} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {25E133DF-507B-422A-91FD-4E36155ABF7A} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA} = {D3355CC9-A400-49B7-ADCE-F623A816D1B5} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {6FE31029-BBCA-40A0-81A4-79C05FE08285} - EndGlobalSection -EndGlobal diff --git a/EncConverters-mono.sln b/EncConverters-mono.sln deleted file mode 100644 index a4bb161c..00000000 --- a/EncConverters-mono.sln +++ /dev/null @@ -1,666 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Changed paths to use Mono csproj files. -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECInterfaces-mono", "src\ECInterfaces\ECInterfaces-mono.csproj", "{2935E02F-43ED-4670-9A00-A91B0AD3D66C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EncCnvtrs-mono", "src\EncCnvtrs\EncCnvtrs-mono.csproj", "{3E4B908A-4F96-43C5-981B-1AA4B73CCC26}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECFileConverter-mono", "src\ECFileConverter\ECFileConverter-mono.csproj", "{1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIGuesserEC-mono", "src\AIGuesserEC\AIGuesserEC-mono.csproj", "{B718B5F3-A49A-454C-84FD-6D6F59EC7410}" - ProjectSection(ProjectDependencies) = postProject - {2E70A627-605F-4625-8637-A7109DB8B35C} = {2E70A627-605F-4625-8637-A7109DB8B35C} - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DriveAiEncConverter-mono", "src\DriveAiEncConverter\DriveAiEncConverter-mono.csproj", "{088E2974-9588-4EDA-AF7F-869A10DF402A}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - {B718B5F3-A49A-454C-84FD-6D6F59EC7410} = {B718B5F3-A49A-454C-84FD-6D6F59EC7410} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilIndicEncConverters-mono", "src\SilIndicEncConverters\SilIndicEncConverters-mono.csproj", "{DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}" - ProjectSection(ProjectDependencies) = postProject - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ECDriver", "src\ECDriver\windows\ECDriver-mono.vcxproj", "{1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IcuConvEC", "src\IcuEC\IcuConvEC-mono.vcxproj", "{B6F84043-658E-4732-AFCA-BBE07FF465CB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IcuRegexEC", "src\IcuEC\IcuRegexEC-mono.vcxproj", "{F77C7224-DF82-4ADF-A761-773D21B58EF4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IcuTranslitEC", "src\IcuEC\IcuTranslitEC-mono.vcxproj", "{1D0DA000-6192-4B57-A377-7A0A5AB1A121}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IcuEC-mono", "src\IcuEC\IcuEC-mono.csproj", "{D1BAE593-A552-4F1A-8B08-5A1C27875C2F}" - ProjectSection(ProjectDependencies) = postProject - {1D0DA000-6192-4B57-A377-7A0A5AB1A121} = {1D0DA000-6192-4B57-A377-7A0A5AB1A121} - {F77C7224-DF82-4ADF-A761-773D21B58EF4} = {F77C7224-DF82-4ADF-A761-773D21B58EF4} - {B6F84043-658E-4732-AFCA-BBE07FF465CB} = {B6F84043-658E-4732-AFCA-BBE07FF465CB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PyScriptEncConverter", "src\PyScriptEC\PyScriptEncConverter-mono.vcxproj", "{C5808AC0-A52F-4D77-9903-AE6709712B62}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PyScriptEC-mono", "src\PyScriptEC\PyScriptEC-mono.csproj", "{0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerlExpressionEC-mono", "src\PerlExpressionEC\PerlExpressionEC-mono.csproj", "{4704F67B-246D-483C-B840-231F42D7A12B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CcEC-mono", "src\CcEC\CcEC-mono.csproj", "{2E70A627-605F-4625-8637-A7109DB8B35C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestEncCnvtrs-mono", "src\TestEncCnvtrs\TestEncCnvtrs-mono.csproj", "{E13305E0-0AC9-4181-A9AD-3B9B0A479087}" - ProjectSection(ProjectDependencies) = postProject - {1D0DA000-6192-4B57-A377-7A0A5AB1A121} = {1D0DA000-6192-4B57-A377-7A0A5AB1A121} - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9} = {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9} - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} = {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7} - {F77C7224-DF82-4ADF-A761-773D21B58EF4} = {F77C7224-DF82-4ADF-A761-773D21B58EF4} - {2E70A627-605F-4625-8637-A7109DB8B35C} = {2E70A627-605F-4625-8637-A7109DB8B35C} - {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} - {B6F84043-658E-4732-AFCA-BBE07FF465CB} = {B6F84043-658E-4732-AFCA-BBE07FF465CB} - {088E2974-9588-4EDA-AF7F-869A10DF402A} = {088E2974-9588-4EDA-AF7F-869A10DF402A} - {4704F67B-246D-483C-B840-231F42D7A12B} = {4704F67B-246D-483C-B840-231F42D7A12B} - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F} = {D1BAE593-A552-4F1A-8B08-5A1C27875C2F} - {C5808AC0-A52F-4D77-9903-AE6709712B62} = {C5808AC0-A52F-4D77-9903-AE6709712B62} - {B718B5F3-A49A-454C-84FD-6D6F59EC7410} = {B718B5F3-A49A-454C-84FD-6D6F59EC7410} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppDataMover", "src\AppDataMover\AppDataMover.csproj", "{AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}" - ProjectSection(ProjectDependencies) = postProject - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GuesserEC", "src\AIGuesserEC\GuesserEC\GuesserEC.vcxproj", "{7F906C15-8DCD-466E-9AF3-2EF50E7FC046}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Debug|x86 = Debug|x86 - LegacyDebug|Any CPU = LegacyDebug|Any CPU - LegacyDebug|Mixed Platforms = LegacyDebug|Mixed Platforms - LegacyDebug|Win32 = LegacyDebug|Win32 - LegacyDebug|x86 = LegacyDebug|x86 - LegacyRelease|Any CPU = LegacyRelease|Any CPU - LegacyRelease|Mixed Platforms = LegacyRelease|Mixed Platforms - LegacyRelease|Win32 = LegacyRelease|Win32 - LegacyRelease|x86 = LegacyRelease|x86 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - Release|x86 = Release|x86 - Template|Any CPU = Template|Any CPU - Template|Mixed Platforms = Template|Mixed Platforms - Template|Win32 = Template|Win32 - Template|x86 = Template|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Any CPU.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|Win32.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|x86.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Debug|x86.Build.0 = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyDebug|x86.Build.0 = Debug|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|x86.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.LegacyRelease|x86.Build.0 = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Any CPU.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Mixed Platforms.Build.0 = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|Win32.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|x86.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Release|x86.Build.0 = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Any CPU.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Mixed Platforms.Build.0 = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|Win32.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|x86.ActiveCfg = Release|x86 - {2935E02F-43ED-4670-9A00-A91B0AD3D66C}.Template|x86.Build.0 = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Any CPU.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|Win32.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|x86.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Debug|x86.Build.0 = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyDebug|x86.Build.0 = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|x86.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.LegacyRelease|x86.Build.0 = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Any CPU.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Mixed Platforms.Build.0 = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|Win32.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|x86.ActiveCfg = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Release|x86.Build.0 = Release|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Any CPU.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Mixed Platforms.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Mixed Platforms.Build.0 = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|Win32.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|x86.ActiveCfg = Debug|x86 - {3E4B908A-4F96-43C5-981B-1AA4B73CCC26}.Template|x86.Build.0 = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Any CPU.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|Win32.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|x86.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Debug|x86.Build.0 = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyDebug|x86.Build.0 = Debug|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|x86.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.LegacyRelease|x86.Build.0 = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Any CPU.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Mixed Platforms.Build.0 = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|Win32.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|x86.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Release|x86.Build.0 = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Any CPU.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Mixed Platforms.Build.0 = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|Win32.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|x86.ActiveCfg = Release|x86 - {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6}.Template|x86.Build.0 = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Any CPU.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|Win32.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|x86.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Debug|x86.Build.0 = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyDebug|x86.Build.0 = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|x86.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.LegacyRelease|x86.Build.0 = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Any CPU.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Mixed Platforms.Build.0 = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|Win32.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|x86.ActiveCfg = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Release|x86.Build.0 = Release|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Any CPU.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Mixed Platforms.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Mixed Platforms.Build.0 = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|Win32.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|x86.ActiveCfg = Debug|x86 - {B718B5F3-A49A-454C-84FD-6D6F59EC7410}.Template|x86.Build.0 = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|Win32.ActiveCfg = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|x86.ActiveCfg = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Debug|x86.Build.0 = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Any CPU.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Any CPU.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|Win32.ActiveCfg = Debug|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyDebug|x86.Build.0 = Debug|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Any CPU.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Any CPU.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Mixed Platforms.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|Win32.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|x86.ActiveCfg = Release|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.LegacyRelease|x86.Build.0 = Release|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Any CPU.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Mixed Platforms.Build.0 = Release|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|Win32.ActiveCfg = Release|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|x86.ActiveCfg = Release|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Release|x86.Build.0 = Release|x86 - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Any CPU.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Any CPU.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Mixed Platforms.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Mixed Platforms.Build.0 = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|Win32.ActiveCfg = Release|Any CPU - {088E2974-9588-4EDA-AF7F-869A10DF402A}.Template|x86.ActiveCfg = Release|Any CPU - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Any CPU.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|Win32.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|x86.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Debug|x86.Build.0 = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyDebug|x86.Build.0 = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|x86.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.LegacyRelease|x86.Build.0 = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Any CPU.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Mixed Platforms.Build.0 = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|Win32.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|x86.ActiveCfg = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Release|x86.Build.0 = Release|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Any CPU.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Mixed Platforms.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Mixed Platforms.Build.0 = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|Win32.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|x86.ActiveCfg = Debug|x86 - {DC0A7A02-87B7-4619-B45F-D5A3ECB599A9}.Template|x86.Build.0 = Debug|x86 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Win32.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|Win32.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|x86.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Debug|x86.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|Win32.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Any CPU.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Mixed Platforms.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Win32.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|Win32.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|x86.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Release|x86.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Any CPU.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Mixed Platforms.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Win32.ActiveCfg = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|Win32.Build.0 = Release|Win32 - {1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}.Template|x86.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Win32.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|Win32.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|x86.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Debug|x86.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|Win32.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Any CPU.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Mixed Platforms.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Win32.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|Win32.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|x86.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Release|x86.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Any CPU.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Mixed Platforms.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Win32.ActiveCfg = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|Win32.Build.0 = Release|Win32 - {B6F84043-658E-4732-AFCA-BBE07FF465CB}.Template|x86.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Win32.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|Win32.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|x86.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Debug|x86.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|Win32.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Any CPU.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Mixed Platforms.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Win32.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|Win32.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|x86.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Release|x86.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Any CPU.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Mixed Platforms.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Win32.ActiveCfg = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|Win32.Build.0 = Release|Win32 - {F77C7224-DF82-4ADF-A761-773D21B58EF4}.Template|x86.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Win32.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|Win32.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|x86.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Debug|x86.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|Win32.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Any CPU.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Mixed Platforms.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Win32.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|Win32.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|x86.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Release|x86.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Any CPU.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Mixed Platforms.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Win32.ActiveCfg = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|Win32.Build.0 = Release|Win32 - {1D0DA000-6192-4B57-A377-7A0A5AB1A121}.Template|x86.ActiveCfg = Release|Win32 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Any CPU.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|Win32.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|x86.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Debug|x86.Build.0 = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyDebug|x86.Build.0 = Debug|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|x86.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.LegacyRelease|x86.Build.0 = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Any CPU.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Mixed Platforms.Build.0 = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|Win32.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|x86.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Release|x86.Build.0 = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Any CPU.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Mixed Platforms.Build.0 = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|Win32.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|x86.ActiveCfg = Release|x86 - {D1BAE593-A552-4F1A-8B08-5A1C27875C2F}.Template|x86.Build.0 = Release|x86 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Win32.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|Win32.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|x86.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Debug|x86.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Any CPU.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Mixed Platforms.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Win32.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|Win32.Build.0 = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyDebug|x86.ActiveCfg = Debug|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Any CPU.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Mixed Platforms.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Win32.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|Win32.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.LegacyRelease|x86.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Any CPU.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Mixed Platforms.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Win32.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|Win32.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|x86.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Release|x86.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Any CPU.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Mixed Platforms.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Win32.ActiveCfg = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|Win32.Build.0 = Release|Win32 - {C5808AC0-A52F-4D77-9903-AE6709712B62}.Template|x86.ActiveCfg = Release|Win32 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Any CPU.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|Win32.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|x86.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Debug|x86.Build.0 = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyDebug|x86.Build.0 = Debug|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|x86.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.LegacyRelease|x86.Build.0 = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Any CPU.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Mixed Platforms.Build.0 = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|Win32.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|x86.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Release|x86.Build.0 = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Any CPU.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Mixed Platforms.Build.0 = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|Win32.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|x86.ActiveCfg = Release|x86 - {0DFDDA0B-9EBF-4238-8A2B-D4C2B4F745D7}.Template|x86.Build.0 = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Any CPU.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|Win32.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|x86.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Debug|x86.Build.0 = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyDebug|x86.Build.0 = Debug|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|x86.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.LegacyRelease|x86.Build.0 = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Any CPU.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Mixed Platforms.Build.0 = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|Win32.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|x86.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Release|x86.Build.0 = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Any CPU.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Mixed Platforms.Build.0 = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|Win32.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|x86.ActiveCfg = Release|x86 - {4704F67B-246D-483C-B840-231F42D7A12B}.Template|x86.Build.0 = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Any CPU.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|Win32.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|x86.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Debug|x86.Build.0 = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyDebug|x86.Build.0 = Debug|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|x86.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.LegacyRelease|x86.Build.0 = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Any CPU.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Mixed Platforms.Build.0 = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|Win32.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|x86.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Release|x86.Build.0 = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Any CPU.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Mixed Platforms.Build.0 = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|Win32.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|x86.ActiveCfg = Release|x86 - {2E70A627-605F-4625-8637-A7109DB8B35C}.Template|x86.Build.0 = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Any CPU.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|Win32.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|x86.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Debug|x86.Build.0 = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyDebug|x86.Build.0 = Debug|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|x86.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.LegacyRelease|x86.Build.0 = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Any CPU.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Mixed Platforms.Build.0 = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|Win32.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|x86.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Release|x86.Build.0 = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Any CPU.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Mixed Platforms.Build.0 = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|Win32.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|x86.ActiveCfg = Release|x86 - {E13305E0-0AC9-4181-A9AD-3B9B0A479087}.Template|x86.Build.0 = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Any CPU.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|Win32.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|x86.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Debug|x86.Build.0 = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Any CPU.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Mixed Platforms.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Mixed Platforms.Build.0 = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|Win32.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|x86.ActiveCfg = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyDebug|x86.Build.0 = Debug|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Any CPU.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Mixed Platforms.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Mixed Platforms.Build.0 = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|Win32.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|x86.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.LegacyRelease|x86.Build.0 = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Any CPU.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Mixed Platforms.Build.0 = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|Win32.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|x86.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Release|x86.Build.0 = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Any CPU.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Mixed Platforms.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Mixed Platforms.Build.0 = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|Win32.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|x86.ActiveCfg = Release|x86 - {AC397DFB-5A78-43FF-AB14-83FCAE39ECEC}.Template|x86.Build.0 = Release|x86 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Win32.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|Win32.Build.0 = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Debug|x86.ActiveCfg = Debug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Any CPU.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Mixed Platforms.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Mixed Platforms.Build.0 = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Win32.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|Win32.Build.0 = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyDebug|x86.ActiveCfg = LegacyDebug|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Any CPU.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Mixed Platforms.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Mixed Platforms.Build.0 = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Win32.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|Win32.Build.0 = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.LegacyRelease|x86.ActiveCfg = LegacyRelease|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Any CPU.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Mixed Platforms.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Win32.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|Win32.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Release|x86.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Any CPU.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Mixed Platforms.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Mixed Platforms.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Win32.ActiveCfg = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|Win32.Build.0 = Release|Win32 - {7F906C15-8DCD-466E-9AF3-2EF50E7FC046}.Template|x86.ActiveCfg = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal From 39e9e9e21073d241b8af9cc5fb5317219232cf5f Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 19:59:25 -0500 Subject: [PATCH 020/113] try to fix the linux build by quoting the solution file (since it has a space in it) and the nuget packaging to use nuget rather than dotnet pack (since I'm using a nuspec file) --- .github/workflows/build.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15515f64..54847170 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,13 +39,18 @@ jobs: run: msbuild /m /p:Configuration=${{matrix.build_configuration}} "${{env.SOLUTION_FILE_PATH}}" - name: Create NuGet Package - run: dotnet pack -c ${{ matrix.build_configuration }} -o ./output + run: nuget pack Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} + if: matrix.build_configuration == 'Debug' + + - name: Create NuGet Package + run: nuget pack Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} + if: matrix.build_configuration == 'Release' - name: Upload NuGet Package as Artifact uses: actions/upload-artifact@v2 with: - name: nuget-package - path: ./output/*.nupkg + name: ${{matrix.build_configuration}}-nuget-package + path: ./output/${{matrix.build_configuration}}/*.nupkg # TODO Run tests #- name: Test @@ -68,7 +73,7 @@ jobs: run: sudo apt-get install --assume-yes automake g++ python2-dev python2 libicu-dev mono5-sil icu-dev-fw libteckit-dev - name: Restore NuGet Packages - run: nuget restore "${{env.SOLUTION_FILE_PATH}}" + run: nuget restore "'${{env.SOLUTION_FILE_PATH}}'" - name: Checkout uses: actions/checkout@v2 From 390f96452977fee977e1dc633a3018b8b8bca1b8 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 20:16:45 -0500 Subject: [PATCH 021/113] indicate correct path to nuspec and ls the linux root folder to see why it can't seem to find the solution file that's in the root of the repo --- .github/workflows/build.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54847170..f3249867 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,11 +39,11 @@ jobs: run: msbuild /m /p:Configuration=${{matrix.build_configuration}} "${{env.SOLUTION_FILE_PATH}}" - name: Create NuGet Package - run: nuget pack Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} + run: nuget pack ./Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} if: matrix.build_configuration == 'Debug' - name: Create NuGet Package - run: nuget pack Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} + run: nuget pack ./Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} if: matrix.build_configuration == 'Release' - name: Upload NuGet Package as Artifact @@ -72,8 +72,11 @@ jobs: - name: Install dependencies run: sudo apt-get install --assume-yes automake g++ python2-dev python2 libicu-dev mono5-sil icu-dev-fw libteckit-dev + - name: List Files in Repository + run: ls -R + - name: Restore NuGet Packages - run: nuget restore "'${{env.SOLUTION_FILE_PATH}}'" + run: nuget restore "${{env.SOLUTION_FILE_PATH}}" - name: Checkout uses: actions/checkout@v2 From 1b22232ec65fa7048dbfbd866d39784cf4388a16 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 20:27:24 -0500 Subject: [PATCH 022/113] duh... can't restore until after you checkout... prepend the file paths in the nuspec file w/ ".\" to help GHA find them properly --- .github/workflows/build.yml | 6 +++--- Package.nuspec | 34 +++++++++++++++++----------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f3249867..f6007a23 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,15 +72,15 @@ jobs: - name: Install dependencies run: sudo apt-get install --assume-yes automake g++ python2-dev python2 libicu-dev mono5-sil icu-dev-fw libteckit-dev + - name: Checkout + uses: actions/checkout@v2 + - name: List Files in Repository run: ls -R - name: Restore NuGet Packages run: nuget restore "${{env.SOLUTION_FILE_PATH}}" - - name: Checkout - uses: actions/checkout@v2 - - name: Autogen run: . environ && ./autogen.sh diff --git a/Package.nuspec b/Package.nuspec index dc06acda..e83f22f8 100644 --- a/Package.nuspec +++ b/Package.nuspec @@ -18,18 +18,18 @@ ReadMe.md - + - - + + - - + + - + - - - - - - - - + + + + + + + + - - - + + + \ No newline at end of file From 2c4682286cefb50a8550ba5d50950122fff0ed55 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 20:44:38 -0500 Subject: [PATCH 023/113] where or where have my output files gone? --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f6007a23..16c6db3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,6 +38,9 @@ jobs: # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference run: msbuild /m /p:Configuration=${{matrix.build_configuration}} "${{env.SOLUTION_FILE_PATH}}" + - name: List Files in Repository + run: dir /s + - name: Create NuGet Package run: nuget pack ./Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} if: matrix.build_configuration == 'Debug' From c842d91e61d1e64bdde92ada68aac2475ebafd16 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 20:50:52 -0500 Subject: [PATCH 024/113] try, try again --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 16c6db3b..80c9d360 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: run: msbuild /m /p:Configuration=${{matrix.build_configuration}} "${{env.SOLUTION_FILE_PATH}}" - name: List Files in Repository - run: dir /s + run: dir ./ /s - name: Create NuGet Package run: nuget pack ./Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} From 9a3be87b6110871788b72d9909b29c1c007b719a Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 20:56:20 -0500 Subject: [PATCH 025/113] try 3 --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80c9d360..10cb2a93 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,8 @@ jobs: run: msbuild /m /p:Configuration=${{matrix.build_configuration}} "${{env.SOLUTION_FILE_PATH}}" - name: List Files in Repository - run: dir ./ /s + run: dir /s + shell: cmd - name: Create NuGet Package run: nuget pack ./Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} From d399c06c0587667b68a7b33df4087563c26bb8b0 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 21:13:59 -0500 Subject: [PATCH 026/113] create separate nuspec files for debug vs. release --- .github/workflows/build.yml | 7 +-- EncConverters 2019.sln | 3 +- Package.Debug.nuspec | 65 ++++++++++++++++++++++++ Package.nuspec => Package.Release.nuspec | 0 4 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 Package.Debug.nuspec rename Package.nuspec => Package.Release.nuspec (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10cb2a93..fc890957 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,12 +43,7 @@ jobs: shell: cmd - name: Create NuGet Package - run: nuget pack ./Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - if: matrix.build_configuration == 'Debug' - - - name: Create NuGet Package - run: nuget pack ./Package.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - if: matrix.build_configuration == 'Release' + run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - name: Upload NuGet Package as Artifact uses: actions/upload-artifact@v2 diff --git a/EncConverters 2019.sln b/EncConverters 2019.sln index 4c03539d..fed6bec3 100644 --- a/EncConverters 2019.sln +++ b/EncConverters 2019.sln @@ -153,7 +153,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .github\workflows\build.yml = .github\workflows\build.yml build\Encoding-Converters-Core.props = build\Encoding-Converters-Core.props - Package.nuspec = Package.nuspec + Package.Debug.nuspec = Package.Debug.nuspec + Package.Release.nuspec = Package.Release.nuspec EndProjectSection EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "EcFolderACLsMM", "installer\EcFolderACLsMM\EcFolderACLsMM.wixproj", "{F7483CF4-5AB5-4E62-B87E-A6A88EC228DC}" diff --git a/Package.Debug.nuspec b/Package.Debug.nuspec new file mode 100644 index 00000000..f4608160 --- /dev/null +++ b/Package.Debug.nuspec @@ -0,0 +1,65 @@ + + + + Encoding-Converters-Core + 0.8.0 + Bob Eaton, Jim Kornelson, SIL International + jnaylor, sillsdev + MIT + https://github.com/silnrsi/encoding-converters-core + false + Libraries and merge modules for core encoding converter functionality. + Includes managed DLL (for including in projects as nuget artifacts) in the .\lib\net48\... folder, and other managed and non-managed (read: non-nuget) resources that optionally may be manually added to projects or at least in installers in the .\runtimes\... folder -- including plugin definitions, tlb, and exe files for both Win32/x86 and x64. Some of the resources are also included in various merge modules in the .\installer\MergeModules... folder + Copyright 2017-2023 + + + + + ReadMe.md + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Package.nuspec b/Package.Release.nuspec similarity index 100% rename from Package.nuspec rename to Package.Release.nuspec From bdc6c3375b4e9247995fea1a73151fd3fe3ffc77 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 21:25:14 -0500 Subject: [PATCH 027/113] fixed the pyscript by removing the removed package from the *.csproj file and added both the Win32 and x64 builds to the GHA yaml file --- .github/workflows/build.yml | 3 ++- src/PyScriptEC/PyScriptEC 2010.csproj | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc890957..5d938378 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,6 +21,7 @@ jobs: fail-fast: false matrix: build_configuration: ["Debug", "Release"] + build_platform: ["x64", "Win32"] steps: - name: Checkout @@ -36,7 +37,7 @@ jobs: working-directory: ${{env.GITHUB_WORKSPACE}} # Add additional options to the MSBuild command line here (like platform or verbosity level). # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference - run: msbuild /m /p:Configuration=${{matrix.build_configuration}} "${{env.SOLUTION_FILE_PATH}}" + run: msbuild /m /p:Configuration=${{matrix.build_configuration}} /p:Platform=${{ matrix.build_platform }} "${{env.SOLUTION_FILE_PATH}}" - name: List Files in Repository run: dir /s diff --git a/src/PyScriptEC/PyScriptEC 2010.csproj b/src/PyScriptEC/PyScriptEC 2010.csproj index ad5cfdbe..3cea17ae 100644 --- a/src/PyScriptEC/PyScriptEC 2010.csproj +++ b/src/PyScriptEC/PyScriptEC 2010.csproj @@ -84,12 +84,9 @@ - + ..\..\packages\pythonnet.3.0.3\lib\netstandard2.0\Python.Runtime.dll - - ..\..\packages\Python.Runtime.AllPlatforms.3.7.2.4\runtimes\linux-x64\lib\netstandard2.0\Python.Runtime.dll - 3.5 From 3c70a1666d66164cfddd7689b3f983a9d99a7bb6 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 21:53:51 -0500 Subject: [PATCH 028/113] trying something to get all builds data into the same location for the nuget packaging --- .github/workflows/build.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d938378..fc71f0d7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,6 +39,14 @@ jobs: # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference run: msbuild /m /p:Configuration=${{matrix.build_configuration}} /p:Platform=${{ matrix.build_platform }} "${{env.SOLUTION_FILE_PATH}}" + - name: Copy files to common location + run: | + cp -r ./output/${{ matrix.build_platform }}/${{ matrix.build_configuration }}/* ./output/Common/${{ matrix.build_platform }}/${{ matrix.build_configuration }} + + - name: Copy files back for nuget packaging + run: | + cp -r ./output/Common/* ./output + - name: List Files in Repository run: dir /s shell: cmd From 19c161bfab32132f25a8cac3fb032f9a212480b3 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 21:59:59 -0500 Subject: [PATCH 029/113] move out of the same tree --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc71f0d7..e6902391 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,11 +41,11 @@ jobs: - name: Copy files to common location run: | - cp -r ./output/${{ matrix.build_platform }}/${{ matrix.build_configuration }}/* ./output/Common/${{ matrix.build_platform }}/${{ matrix.build_configuration }} + cp -r ./output/${{ matrix.build_platform }}/${{ matrix.build_configuration }}/* ./Common/${{ matrix.build_platform }}/${{ matrix.build_configuration }} - name: Copy files back for nuget packaging run: | - cp -r ./output/Common/* ./output + cp -r ./Common/* ./output - name: List Files in Repository run: dir /s From f8faf6fab275b83fd4976770dae20992d1b30abe Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 22:07:50 -0500 Subject: [PATCH 030/113] try with xcopy so the folders are created if they don't exist --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e6902391..5728071d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,8 @@ jobs: - name: Copy files to common location run: | - cp -r ./output/${{ matrix.build_platform }}/${{ matrix.build_configuration }}/* ./Common/${{ matrix.build_platform }}/${{ matrix.build_configuration }} + xcopy /s /i .\output\${{ matrix.build_platform }}/${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}/${{ matrix.build_configuration }}\ + # cp -r ./output/${{ matrix.build_platform }}/${{ matrix.build_configuration }}/* ./Common/${{ matrix.build_platform }}/${{ matrix.build_configuration }} - name: Copy files back for nuget packaging run: | From 569555fee962f9cd87bea76959769bcaf3f3462b Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 22:13:05 -0500 Subject: [PATCH 031/113] try w/ shell: cmd --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5728071d..cd627948 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,13 +41,14 @@ jobs: - name: Copy files to common location run: | - xcopy /s /i .\output\${{ matrix.build_platform }}/${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}/${{ matrix.build_configuration }}\ + xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ + shell: cmd # cp -r ./output/${{ matrix.build_platform }}/${{ matrix.build_configuration }}/* ./Common/${{ matrix.build_platform }}/${{ matrix.build_configuration }} - name: Copy files back for nuget packaging run: | cp -r ./Common/* ./output - + - name: List Files in Repository run: dir /s shell: cmd From 0db1d86f2669e0d03f134689f4d15d302654123b Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 22:17:34 -0500 Subject: [PATCH 032/113] remove shell: cmd after fixing xcopy --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd627948..3aaac957 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,8 +42,6 @@ jobs: - name: Copy files to common location run: | xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - shell: cmd - # cp -r ./output/${{ matrix.build_platform }}/${{ matrix.build_configuration }}/* ./Common/${{ matrix.build_platform }}/${{ matrix.build_configuration }} - name: Copy files back for nuget packaging run: | From 7aa127e6d708adb8195d87924796402968f5488f Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 22:24:03 -0500 Subject: [PATCH 033/113] when copying back to output (so nuspec can find them) use xcopy, bkz cp doesn't like to overwrite --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3aaac957..f817eb1b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,9 +43,9 @@ jobs: run: | xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - - name: Copy files back for nuget packaging + - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) run: | - cp -r ./Common/* ./output + xcopy /y .\Common]* .\output - name: List Files in Repository run: dir /s From 210e1a00248a8eb6fff718d90eafa19e4d7cb378 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 22:32:23 -0500 Subject: [PATCH 034/113] fix typo --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f817eb1b..1c820f39 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,8 +44,9 @@ jobs: xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' run: | - xcopy /y .\Common]* .\output + xcopy /s /y .\Common\* .\output - name: List Files in Repository run: dir /s From 28510476a9eb600fc705ceb0919ebbbc105eae64 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 31 Oct 2023 22:44:23 -0500 Subject: [PATCH 035/113] limit the nuget packaging until all the all the different build jobs have finished --- .github/workflows/build.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1c820f39..ffb71c32 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,19 +43,21 @@ jobs: run: | xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' + - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) + if: matrix.build_configuration == 'Release' run: | - xcopy /s /y .\Common\* .\output + xcopy /s /y .\Common\${{matrix.build_platform}}\* .\output\${{matrix.build_platform}} - name: List Files in Repository run: dir /s shell: cmd - name: Create NuGet Package + if: matrix.build_platform == 'Win32' run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - name: Upload NuGet Package as Artifact + if: matrix.build_platform == 'Win32' uses: actions/upload-artifact@v2 with: name: ${{matrix.build_configuration}}-nuget-package From 58749741ff6f4515c24dd48f8efb591118dc6cd3 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 10:28:34 -0500 Subject: [PATCH 036/113] adjusted where the built merge modules are put to simplify the GHA build and updated the nuspec file --- .github/workflows/build.yml | 13 ++++++----- EncConverters 2019.sln | 4 ++-- Package.Debug.nuspec | 2 +- Package.Release.nuspec | 2 +- .../AIGuesser64bitMM/AIGuesser64bitMM.wixproj | 10 ++++----- installer/AIGuesserMM/AIGuesserMM.wixproj | 6 ++--- installer/CcDLLs64bitMM/CcDLLs64bitMM.wixproj | 4 ++-- installer/CcDLLsMM/CcDLLsMM.wixproj | 6 ++--- .../EC_40_64bit_MM/EC_40_64bit_MM.wixproj | 8 +++---- installer/EC_40_MM/EC_40_MM.wixproj | 6 ++--- .../EcFolderACLsMM/EcFolderACLsMM.wixproj | 4 ++-- .../EcTranslators64bitMM.wixproj | 10 ++++----- .../EcTranslatorsMM/EcTranslatorsMM.wixproj | 10 ++++----- installer/FireFox/FireFox.wixproj | 6 ++--- installer/FireFox64bit/FireFox64.wixproj | 21 +++++------------- installer/ICU_40/ICU_40.wixproj | 8 +++---- installer/ICU_40_64bit/ICU_40_64bit.wixproj | 8 +++---- .../MergeModules hide/EcFolderACLsMM.msm | Bin 0 -> 249856 bytes .../MergeModules hide/EcFolderACLsMM.wixpdb | Bin 0 -> 167273 bytes installer/PerlEc64bitMM/PerlEc64bitMM.wixproj | 8 +++---- installer/PerlEcMM/PerlEcMM.wixproj | 6 ++--- .../PythonEc64bitMM/PythonEc64bitMM.wixproj | 8 +++---- installer/PythonEcMM/PythonEcMM.wixproj | 4 ++-- .../TECkit64bitDllsMM.wixproj | 8 +++---- installer/TECkitDLLsMM/TECkitDLLsMM.wixproj | 8 +++---- .../AzureOpenAiExe/AzureOpenAiExe.csproj | 4 ++-- 26 files changed, 84 insertions(+), 90 deletions(-) create mode 100644 installer/MergeModules hide/EcFolderACLsMM.msm create mode 100644 installer/MergeModules hide/EcFolderACLsMM.wixpdb diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ffb71c32..a6f55154 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,22 +42,25 @@ jobs: - name: Copy files to common location run: | xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - + + publish_nuget: + runs-on: windows-2019 + steps: - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) - if: matrix.build_configuration == 'Release' + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' run: | - xcopy /s /y .\Common\${{matrix.build_platform}}\* .\output\${{matrix.build_platform}} + xcopy /s /y .\Common\* .\output - name: List Files in Repository run: dir /s shell: cmd - name: Create NuGet Package - if: matrix.build_platform == 'Win32' + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - name: Upload NuGet Package as Artifact - if: matrix.build_platform == 'Win32' + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' uses: actions/upload-artifact@v2 with: name: ${{matrix.build_configuration}}-nuget-package diff --git a/EncConverters 2019.sln b/EncConverters 2019.sln index fed6bec3..4327fbd4 100644 --- a/EncConverters 2019.sln +++ b/EncConverters 2019.sln @@ -498,8 +498,8 @@ Global {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Release|x64.Build.0 = Release|x64 {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Win32.ActiveCfg = Release|x86 {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|Win32.Build.0 = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x64.ActiveCfg = Release|x86 - {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x64.Build.0 = Release|x86 + {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x64.ActiveCfg = Release|x64 + {4BF6846B-4DB1-4C91-9435-43E1077BEEE4}.Template|x64.Build.0 = Release|x64 {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Debug|Win32.ActiveCfg = Debug|x64 {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Debug|x64.ActiveCfg = Debug|x64 {8C8AF4F6-2E50-4195-BDBE-499CE90E52CA}.Release|Win32.ActiveCfg = Release|x64 diff --git a/Package.Debug.nuspec b/Package.Debug.nuspec index f4608160..d60e3b37 100644 --- a/Package.Debug.nuspec +++ b/Package.Debug.nuspec @@ -58,7 +58,7 @@ - + diff --git a/Package.Release.nuspec b/Package.Release.nuspec index e83f22f8..38f29e71 100644 --- a/Package.Release.nuspec +++ b/Package.Release.nuspec @@ -58,7 +58,7 @@ - + diff --git a/installer/AIGuesser64bitMM/AIGuesser64bitMM.wixproj b/installer/AIGuesser64bitMM/AIGuesser64bitMM.wixproj index 208ad324..a53eacb2 100644 --- a/installer/AIGuesser64bitMM/AIGuesser64bitMM.wixproj +++ b/installer/AIGuesser64bitMM/AIGuesser64bitMM.wixproj @@ -11,17 +11,17 @@ AIGuesser64bitMM - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ - - - + + + diff --git a/installer/AIGuesserMM/AIGuesserMM.wixproj b/installer/AIGuesserMM/AIGuesserMM.wixproj index e08b31d9..ea852523 100644 --- a/installer/AIGuesserMM/AIGuesserMM.wixproj +++ b/installer/AIGuesserMM/AIGuesserMM.wixproj @@ -1,7 +1,7 @@ - Debug + Release x86 3.11 {406ea033-1918-4ce2-ae3d-1ac9b14cf111} @@ -10,12 +10,12 @@ Module - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ diff --git a/installer/CcDLLs64bitMM/CcDLLs64bitMM.wixproj b/installer/CcDLLs64bitMM/CcDLLs64bitMM.wixproj index d029d45a..1a49d580 100644 --- a/installer/CcDLLs64bitMM/CcDLLs64bitMM.wixproj +++ b/installer/CcDLLs64bitMM/CcDLLs64bitMM.wixproj @@ -11,12 +11,12 @@ CcDLLs64bitMM - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ diff --git a/installer/CcDLLsMM/CcDLLsMM.wixproj b/installer/CcDLLsMM/CcDLLsMM.wixproj index f9785083..78273149 100644 --- a/installer/CcDLLsMM/CcDLLsMM.wixproj +++ b/installer/CcDLLsMM/CcDLLsMM.wixproj @@ -1,7 +1,7 @@ - Debug + Release x86 3.11 {69904b85-6945-4369-a2e3-79dd7319fb53} @@ -10,12 +10,12 @@ Module - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ diff --git a/installer/EC_40_64bit_MM/EC_40_64bit_MM.wixproj b/installer/EC_40_64bit_MM/EC_40_64bit_MM.wixproj index 5b7b2f24..15fa179f 100644 --- a/installer/EC_40_64bit_MM/EC_40_64bit_MM.wixproj +++ b/installer/EC_40_64bit_MM/EC_40_64bit_MM.wixproj @@ -11,12 +11,12 @@ Debug - bin\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/EC_40_MM/EC_40_MM.wixproj b/installer/EC_40_MM/EC_40_MM.wixproj index b09c203d..03ba9b4d 100644 --- a/installer/EC_40_MM/EC_40_MM.wixproj +++ b/installer/EC_40_MM/EC_40_MM.wixproj @@ -1,7 +1,7 @@ - Debug + Release x86 3.11 {dbf25a0c-5f5b-4060-ac5c-cdc50c4aa014} @@ -10,12 +10,12 @@ Module - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ diff --git a/installer/EcFolderACLsMM/EcFolderACLsMM.wixproj b/installer/EcFolderACLsMM/EcFolderACLsMM.wixproj index 27b21371..9ed8473c 100644 --- a/installer/EcFolderACLsMM/EcFolderACLsMM.wixproj +++ b/installer/EcFolderACLsMM/EcFolderACLsMM.wixproj @@ -1,7 +1,7 @@ - Debug + Release x86 3.11 f7483cf4-5ab5-4e62-b87e-a6a88ec228dc @@ -15,7 +15,7 @@ Debug - ..\MergeModules\ + ..\..\output\MergeModules\ obj\$(Configuration)\ diff --git a/installer/EcTranslators64bitMM/EcTranslators64bitMM.wixproj b/installer/EcTranslators64bitMM/EcTranslators64bitMM.wixproj index 6f6f9896..d6c1e0e7 100644 --- a/installer/EcTranslators64bitMM/EcTranslators64bitMM.wixproj +++ b/installer/EcTranslators64bitMM/EcTranslators64bitMM.wixproj @@ -1,7 +1,7 @@ - Debug + Release x64 3.11 {9628E44E-C407-4EA3-95AF-C7E4310EB9D3} @@ -10,13 +10,13 @@ Module - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/EcTranslatorsMM/EcTranslatorsMM.wixproj b/installer/EcTranslatorsMM/EcTranslatorsMM.wixproj index b5aaf451..cd4def88 100644 --- a/installer/EcTranslatorsMM/EcTranslatorsMM.wixproj +++ b/installer/EcTranslatorsMM/EcTranslatorsMM.wixproj @@ -1,7 +1,7 @@ - Debug + Release x86 3.11 {9FAB4338-F089-4279-A5DF-AF5FC0368783} @@ -10,13 +10,13 @@ Module - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/FireFox/FireFox.wixproj b/installer/FireFox/FireFox.wixproj index aa97b734..82206694 100644 --- a/installer/FireFox/FireFox.wixproj +++ b/installer/FireFox/FireFox.wixproj @@ -1,7 +1,7 @@ - Debug + Release x86 3.11 e4de895c-b714-4fa7-b9de-20eb2e4d78fd @@ -10,12 +10,12 @@ Module - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ diff --git a/installer/FireFox64bit/FireFox64.wixproj b/installer/FireFox64bit/FireFox64.wixproj index bb974a57..408085cf 100644 --- a/installer/FireFox64bit/FireFox64.wixproj +++ b/installer/FireFox64bit/FireFox64.wixproj @@ -1,31 +1,22 @@ - Debug - x86 + Release + x64 3.11 823FD7A4-C5F9-4600-A9B8-49EF274BF5B8 2.0 EcFireFox64 Module - - bin\$(Configuration)\ - obj\$(Configuration)\ - Debug - - - ..\MergeModules\$(Platform)\ - obj\$(Configuration)\ - Debug - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/ICU_40/ICU_40.wixproj b/installer/ICU_40/ICU_40.wixproj index d6dfa7e2..4848decc 100644 --- a/installer/ICU_40/ICU_40.wixproj +++ b/installer/ICU_40/ICU_40.wixproj @@ -11,12 +11,12 @@ Debug - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/ICU_40_64bit/ICU_40_64bit.wixproj b/installer/ICU_40_64bit/ICU_40_64bit.wixproj index ccbf9d97..256e6c7c 100644 --- a/installer/ICU_40_64bit/ICU_40_64bit.wixproj +++ b/installer/ICU_40_64bit/ICU_40_64bit.wixproj @@ -11,12 +11,12 @@ Debug - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/MergeModules hide/EcFolderACLsMM.msm b/installer/MergeModules hide/EcFolderACLsMM.msm new file mode 100644 index 0000000000000000000000000000000000000000..48b8aff3197268953b8d6be5420109e6d8b0be20 GIT binary patch literal 249856 zcmeFa4}4U`)jxdmkE{^bAVg831_VVxM8m%bN`Ne4CAt{cfEa}eIHU*)yBeyIz$TjQ z5{oS=t!T0SqZKPwsHlihQJ|tyr4=iE#K*Lq?dEBtq_EZ0{e8b@?!DPWtlGDq-}^rA zhfVI@J7>2r~lX?>o|vAWpsG~As_K)IHcZo@uL zCX+Urg~wx`|3w^d+U?l=7zd7V;1~yvao`vSj&a}^2aa*z7zd7V;1~yvap3>o9QY^J zs$9SG8iT5Gy`PCI8V_)^S9e@JaCvdT1Yq^Vbv&+KxO(Ht!*v3#6LIyy zbrP!>r7mOaGizgY+QqJ4Z(E|uA#Wj z#Wf7qdAQEURfuait`WFK;u?i(G%lxZMfUUmqNVw(j*~EOk?-Q)_ zG}Yn+Aa>*h~C ziWw|0KE;!h32PrD9nO#GPKFDh=HwCaM-M|T;MF{W|!n-}*O^IFlkqD#iSeDNitUmE>lQEAaz zMa5%0MLDCpcH+_Sf200vt4*csg{=Rol9rMsC933`^*c$7uO6sBZDj1uU$^~f)1s}5 zpW?|=e1pc1n(+OSzl~Qu1N$c5X#X_Yjd__y+AdiH0MH|ztw|Bd?7erk(f)ZgTP zMaf}b)5IsojG1u8q)`*{Ck&sYO3s+@RW+dv_nXTf+HS|%q@DcpCsvj;`Ko+_zF|wC z{$i)5O#8b0XWyfpo1fyzGku?wDBq}mQv&87f7-`M@9XAIo3$hViYMoT<0B@_7=I2% z!N_k|d$!{@=RfV`?frlGxVhuco$$?b1`&Kv|1|CauAl6gR{xkt^Y;9 z-O)M!F-^V!|6cyzxc(O)f5i=&|Ip`~^8Y`StxM)u{_Pxaneu<}p*{DnH~#a71a_y3)} z`)_jZy#LRAf6jOGZJ^G1AuiGzhkG%u@wg`7nuv?bAF3gfa8VuPbbJXe;vf4Q{nJH%#<~_Xn$Cbi#CY;xM+uH z#YJ1h5D=q1q6T-`Bi7(fTf`3BX^+^8J82%ko%@hYxO0E28F$*|3y=x(X##PcJ>dC- zOBO8+&RMu{PH@5EMFk~uf^)t-XX!k^8PEMO-=b?5&t0(Sx`K&|7u_^(NpRkhr3I4~ zFPzK!_=!^ru3fxn{(|d5ON4-(j(L_{GNs^>ML=I9F>@B$ajbjkyd~GoD_uM{v~b># zg3_`}hPW9IDL6`gQWn}D%H{=^7TmmKL2zEd4fB>=PfCiQ97ky+Tz6vm(B|o3@RLY-g!gMA3A)*c_Ytq(<0f|`edVLbpGp#9l8GU zcNWf%oQ1tE{td?8xha1ma8_gl>_Hd82ITxrwWeAD{LSk0w*Y=13#>}{`;NuGMe=u} z<^0`Z-D2IA@|TVt+zq|7J9?%UyF@+FBfFsYo{kePXLk5b!Yz$uxdH0k0 z>;T)6$>m@5?8JYaJM-*>$8ZOjjne_v83$qO%gV;MqkU5FYmOH0z>dZT#ucEPoQoX1 z)MppAyuB{qT+Pwo4(#jPQ)v)i=E4-Z{|eTbek!fh=gxRe*ugnUn>i?QKN=r8Abd%H zwq)9kc^@Gs&QcN2wPr|=-VFTAGB@}8T#*oN5Dz!H0Vj2_Q262>M9qBOcTARi|x$~SL%h94qJ8B9bd_rh?VB< z{ZMjjwNn&-WlG2!47~4I4c2NaYTaqwWv#NlZ~cI>l7A_mf+e9v1q+~NU0zmj{o=Xv zhIa4Xb$}gj(ikdFt$cE2)~Q#od|vKXt=uj5ij_aZ{iDA;9)3{n8^aID{paD0xc|^v zW8H1tgYkgBjcHFrEc55UQ;H#vPpuriaud>>8Gj&MnQ>nGN|_*;kPpWw2r zwbqZU`>p$|_0|K{gH}z2L+hZG-mhC)k6i0;nziYpr#|}SM?bY5vK}^0V7b(MFyYf7 z43AmhFF(%Rs)2TtX<2puoq_1$G*k0OEdCu=%RfV=I6cE^1fG?hVQnS>e}+|+#RvN{ zG{f3-nq{$`k6MpeKeHZ}h~S+Y?#aE=bH`(Lm_YJIBJuTeYa_llNN_BQ!d#zlB2(@| zgY&9_2+#UE%Fnu>t}J)zr@*pi|H69G3eK^t-)9pK753o%DXx@Hv1Jtxr6LMgV}E=V zAY*PWqK=0D)WWzk$ImAD!^3LlGCX3O`4p4hl6eakU(0ntf6?%$+fkbvFB;q|(blM? z-6(pQlk$uA&blMR|8MJ#l+YP9nKfB8U23vxJT=GFbVUmi*7-XXvpudI$|vVarPz-9 zMVbb$b1LeyxzJ&~&}4f+tIdISdvsma(PRg9&}C0Y=V{kv%SDSF=jySeI_bpcLX)L7 zI}h{0>4>8yI}k0|1$u0{t;vqF3Z5u@4$t>z-j)7{^^-FMGPxo7{md1U@9zyNxOboi{6}~dG!#FP zes?i2n4bk&1y3YjNIsEy*W`xW`1?^`BI0Xp@U{6He64=n;}4b+iU{xH6Fw%H=6nZD*iheNgbqv~qvclbqT|O6)CH zL(WXk4d|wAmKENS6D>{D?GAQ{rcF)yJ<-y(_P{mK*RJ0Ea;`N!+8k~!E{j&=1W-*+ zVX{oE8knA2nI5Tbi&VEps#_w}3BB)mlFKEF)Rc!2ePX#9i+eI}P_Oh{$@+M;2k8R3 z5;@PD89NseCF*M<&8WwpoSGv@Cn8v;JScoXkC!6m#1?eVBLC3(r#sHIMT)55R8_F>4_`KRX$LJyeR{4782)Yz^U}itjs8Ej8q?tRO^Q6 zjgiu(hU&&ckI$GN@ij($y(>?P_;xX{H|oo+v?9L!;N}$#(+}?SHPdEsMbuN7j)EJ? zDD_&h{0g$%5{?g$Vj*G|BZ^Q3DR}D@>Z%R}2ZprPiBVr`d0A>>mD!CoO1O*0YHe?y z4vp2R8C%-X*o?E>cFZpelouw|K6C*v8Z8+8KpGIum;e_d)lHG=W_`;RyMK38Ex?S8 zLIad1^M*Su*;O^325dev)gx@G`kT((4gEfHT^U8A?Q3()5m zjrP{I0Nmh9U@W!y^~-OWG~W6>0&X?n$6fF*1l(l6IWCw}NrO)taJ3Dtx~aj}Y(W40 zrlDJP6}+I+lA-2gNGC&yWT-Wmtq0*98SyOLAImegQPp|nYA?)D`c?ED0dz-8q0Dtt zu+WH4L^`F;Vwd~{x*tYOe3&XhINncrcsp6`8H8IewVJmaHG{V-Re)PS--0AFXBJhr z1U<=6i~d_Zr9>+Ot@^(ukYFI8e~Uof`@t^BykTH8Mse1Q6JaYW*S9=vS=X=;GtFSk zl{Q?9oTUxXaA-b^#TNZCFs0LVRhtnVd(393w2%Iu9d4{NPXw{(auHvG%|nKwd4jhY zF_-Y`GaVLQP4V_5^g!Xwg)TxD2jO&d1F#)wzTQp-!_5@-J7F5QoScqy(?0^BT~IBQr)P(2YNQ&a@n(g2yI3c<4HH6igk^_ zo=PE9nXa3EWm&QBBKj!fp#tFO2+F$#-!?}K7QSCTQ6yoc!jt?RNcB<&4XFn~DtaV# z4pKGv8vSYrgaXCpt+)$jwi;akmhCI5ZYCF+_4_vwwb`E>ky((DtGDlVOI-uR*dL&) zxg2{^aM3H;{7ib`i>!yY?sDL84l5&9ud~OixBffd;FDIgnwptIB)$g1-{E)*@f^sUHsJo-{G&!Cj505e-Ypu zAm^aixJUQby&pOuTH#R}`laWV>G=>)=sK|;v;%}N0qs=>5P|lYf*2%d@a+Y>GQHfd z^82$r_Mv<3_v^EtVM)U~hDCjzBH!K+rkfTu8W>30lTy#;;iPz^?y$H1BMgW!`-3^* z&oYp+x9&kWjZxxo6pwW|fks4M2sJTACu$rWqoy269kWI*|DWvPZuL z=_jMB)IfIWNe<3%1KFW}>fm@+_zqBBp;)nQD3xkCodZZJ0MPr$TQvd{kE>eVn$#5D z{-FBs_B*9f;rLr>GjF@pD&AgFwP0Y3Ya}(BPZS4gET3-YQ$C*J%T*gYWR=>_+l^{7 zZTES&0D#kF^aleJC{v@p17&`_V3(;Ol&0B4IiFH>4W9Id zU%N4T83P%SP<@~)=sTU5?#eH^!%!@oC?ocBKcZY@bM@rQ6yAN0rm>Jb_+W-G+7~i8eh1 z1qxR;TMRYpQxUQ!W0B)irv}O)Neh#HEP2qQ8O5q_k}BxL&Vjy^l<4%iqNx*mPa5A9O*E?2|A=ESnAT|n^bHMg>)P{E}g_A$}f$t^@E*B3jy zEl{nD=vl6ZJD~2WPa*5IZxdTT{DSZ?m}APF%a zLrfc<1p<}B0?Bv5te!SRtwRc31EJfFa!MzZ9Ym?~a$?wwHDh;nZS zlruY_(S7TB3C8fYP@U$_Aq7S5hlIs1wQ_ zqP*Gx#nTC;nJ7Q)fHE2=*QAbs91L828*ng!vbJ+!01f&v8HiUGzA;O``5uQMXO_|{ zSHo6dOnd*1{kO+y&-Ji2ANNMTt!Y!<=r>I*SXywylEv38nR9)?wR09NS{y9+_Pl>( z|NZ+%Fa3sgU+4O!_TR0a4q3Sc>9>A5cIA4Z^NW>Ja6dEt^YA@#e^TtcXU6?v_w8)| zy<)+&ig|+tNB#JHmNg|U%Nl>f(e1yM9}*a!f6(rki-&J$|CK~c$Ha0sx36pewPt5n zYx6B@{io^JWBKw=0`bME(I_YFzhCzGy7u3pON?Rn-?jgy=3i`CjYF3#U2-jeV(W&@ z8zw3ovhG+=;JNl+)}1^MXM@}?;7vg6vCqHYz=Qd@>A4T(56Z}W<-tCD93YRq`8ZY{ zbNM((9&`9OL>?6%3*^zm$6@lA$;aXHh=Gv%&}csHN&R5rS3_X#p}sW!6)rQEdDRpE z{CYWb%$YOer&L->qaiEPRSn>9x;R-;G9~lYVb-s-^p9S)tO{e^2&jWtK$F(r0W3T$ z)Y<^@>+=k?69YCe=n1KGU_n5Nt8F^rX4os$T2rpVq+bi6iu(%gxG-oJyanS zvV_YlV<_42j*XJ7XejxH_FvKcJ@<0`VOw@Sy9Zopx92?mQi}Bgg&dY=bflzCcgmKn zCIc8Br_aSI5JrQG)NF*YNL>ikWaiAuG%ln)ddKZ3XreB;oGXRnyw4nQw8>>Bs8vW1 z(Ek+tl+1@p<~Eb2Lak45ol5Nv5PKsWWnao>_*1?KuOt!a?v#vf7UbLUDN1?mU}bo0Upz=DD^0;0n{K#v)QBpYN$wb`V;Ns0kq-? zZlZWTmJ)r8iVWhJYPh7nNm8SyB=bBy&8h_EFb{RksZ(kEdA~9(QqdNvNaz>p3`;`! z+k05qHG#_cYBp%-{2yV>u@+A;tSMn4$SEt=_YxP1cyRDhRq@INCh3P*%&Too`h6s2 zH<7Y~{{;^i0#$`Y6^WaMmaFsAt#n8d6bh1zZ!&vjhLqv|D%ZpHvdW?W}922Ve;>o6~pe(t5eT*H zlo_=@i{135(^)ygfjx%&Uob|)J9-N+M^9v1qk^V>5297K* zpN7y&OXjsfgmSqHBvNr8QgJX+(G;m@ja2AJ#lA>Ivvhvge_ucoa1q^AN^pa~VW<=X<2f$=RDtia4UCn7k1-a?0^g#CSoT4Jq5YL2w2ZzF(g`StS)xzkLPJR;>*|gbkw0mnW2PWylP9Q1Lg1N9KRpKk5 zZ{~&rsCWzvogksFwP7QJQ_#TJ;?R(fTe2a)p8H)5{%5 zan#oY-u58dj}xMwBA<(6C-dZMX#e(d$VSzOcE|kJDB~rDNy<{a`=To_SG5&S@oH7e z+f8a3Z;RD|lW|k(VczDbg}hySP<#q;giYl>1Yo<`_Wgf4K%)p^fxB)41d7AmbRkA__a2&^VO3{+D` zxKqat+osb+2Wq;h@USnD&dH)pZ8Jn41yNK>{}a+T-W$;c!5*-{!XiuK`u0y@v{LLB zdbll0s<0u~N(uBS`fvO!r9lVVZZml6r3Ueqqguf=Y`g7{o|6gYrEI%p|B(8aE#1D; zAdJQMzi4&?D!H6M>>Zqd z*}+NO_^y#H_Zv}bYED+~`i-QEtX0I?8C2hxI0y2%th|KRX)tsE;m0 zdd_w*`K<$}TrU>tF*+cbbdfDg?N8?AV+O<~HngO}FQo;01XLpu=s&&$0;P$=FQpUI zLeSd|D3hT4!2rGJfII|ECTODr$|dMlf_~(H(ANTL13|Ytpkjhr2wG}DwY!%Al0O8H zIR+AasqpQA@UXDvkJ&5PFwU16hdI!Wt76<)sd1TZ+GO z+8FoS)VKmSZuB{bdp0$$*o|Arxcg1qiVv+Ctf?C3k9jHBEuhvjY9*pz;6*EB-P|>F zb^~$r2d3R)MvcPFIMWI5KvgFT@TG@Vwt)X zu*ws3^N}Q+QZ_PhqW(Yv2N~$2-&GRqj)4pG0|>w! zzy$6>U{;EBXnBaz!C5_F3{>W#n5Uwcem#8wDh*c@?Umpp29JkUuaijR*CP>z6HVRW zke@p@mqLfQ7;0}o{}j$05JjpipdbAua5!Lk2h^@2j+hI7CPONQl?q%(Pvo4q>_r=C zWI!DNQv5x&1~>gVrW(*GfWJv^1e4e*6Ix!iK}dbFL3npjGy_?Cw~7YPf|zK+AOG*l z{xj!~@dW#++zY^kbe#!ggEAQae>9<=1_XjGx>H;c%z}bTFD$L$MWUaQIYd;e?dR5{ z*MMo+Y8}$X%i#E;`$)6^w-R^}1ST9u(99F{Q|NKh%Gqimgo2%=lbAbFyr~mss0p{{?f`ub-9n809P$7d_4JvR*)t#`Wvj zActu%&c%dQaC3^b%tZgllJxDlY{OQ*uT-c^r{$(T&lH?YLWWFK!Kq|?1)~AxJ za!WbnC?wa9Mk!11r8i@nOiF2!yfl?$O$U<7CHWrUNYtU?H;`mLNqRe#GVw@C#n0(L za;;19_6{UZ4g}O}3=U;+XytY)<724=5Bwyx+Vw8M5nmuUj0E?wgx7Z>7)T`;O(6(} zglK6lMj1x-gy{5~6_~%1%WobPh<;M{cCb75*FE9J^zdKPLWiQS9ogTvap2FAiRD=w z-B7Y2Zh~C~|1Q!qo*pT>I-Vs%8jS0LI6$s(*O~)Fo6WgUx`E?R1V0(0$3nA(=L|I4 z1Ns^iP6p!fw)yNnNIPgX&tdvggOFZ7W#m~8l(uG zZPY_6`*G8~8!Bf@f&mvH>cOJwgQ0At_`C%O)GT$MRe0x*?2qTEO^87j0c3$?!jaf; zlmgYmfYPef#9e?m4zdqj&!RQgQul4eLfFHF@Xf!n%hOd28;8};SttbO7gt@JEBLl6 zO{@L{8<|u^e~?Bp&Bm1`AA_4E_txJiV5~&Nl_t}Lb6qGaU2&y}+D!1)pCfRrbj6is z7nY5NPB*{}jdbJ>)fh9&sgQ~g5GO-`!)Dg33W~XrI^(Bij<}TED?JeY&>MXztkb-; z_gRS0X~8S_1y`5msj6xMQ=B0wa$_eU1=M|&7*A-fp(FZ#i@q;nmn3os!$}Q8LioP{ zCAJ4-nQF7-{`&_dcRSUgdZt?O`RdHEi~@w zK;zarC+B5Ez5yulTGh(7`7WraMn2uZr!{<<&!@S3x(ZJnR-9ec4ir090yq~IpGx5{ ziFj4!MArCJv6{kkoO?`xBU(x?CJLhv8P47+Upt z2#N26SwF03u1Zf;o}<2;NL@W-06a@0b!+6IccgBeJmg2}*2+UcAX2wVo(8};=84p; zMxd~NX+~ zd=p3~nKyvC_x|u_$AXJ@WxeQqCbw55>(z$wtm-6^nl|NOwRaw^Ej_HG#_~Rx~d2$O|H)-i8z0#=o^t55>D&WO_$m+AQ zL{s$unHsCrc&yBVCSa+D1=`LcJ!HMfbqL7y068*8H3BPsu}cd!c43{$o%H2|K9Wfw zyn}@D972PTAfQ*lBn~wZy(yRt1{Z+Av%)WsXBHhuq$T3l1Lp;nTwr|A?+T0^Qeb@0 zuK?EWXwv*^E)oii59|<`ud0wG)E4pRgnY&XMgL{TquKa=9>64~f40`we1NuuY!Ubet#o!I9*J3rmwDQ$i*OakKo#t zg(AVVrwXliVp?bSx&}BR`^9eB0x51}e6hftxnjQy?V_q>o5@+ zIv=4o7^_RO&c=$tK%Wt)N369i`bjKhP?iWRU^GRCTErqW?{_x3QPpqI6@qfiYGt+_EgXHlG5v^+R6wr%c zTgQNjFSO&YV*Duxh(VH5+HgX;Np!PHfWZM>B#B_`Q2P*$4^kU>>!)gYJ6T=DTdxjs zzq@La?2;%pjX<`M@V;4WR@+E;rvz+gv3p zgx}tcs-@Tuhk|~%TFZo>bpb*t69VOVT{4te*chKu7CmJMMhOxV0zD( z6h9ZI7y6@rGniSK9zV5Q6$8NzXT*EJ66J(5Dl@O9qdycn+ey4nVI!0nEI$L-K#9T! zzjKIRo~9R`#ond*O1?MRIIER^*k24IbtY)brGfNsNf64bkX8DLPz z?&W1yvb$kxU_>8|h~_7l7-_QAtw%7ib`=D~udkX%O!P^VzbgsW5b+72)2i=!$e~kU=&&m{ zGE4ms_OdV}V%d^)rngRGa7v5lCn+Kl&y$nkWLhXa`WcCLX4uTEObh6b5D;#5f6zsqOXR6QZfEEwpi$zGp+9KHTusa~ zfl0-c+GRoqY?fjkLhT!guu%};4GvW`p$|fcNvQ;(l?YKF&@zpIf2}C?1Ii#u|7tS} z#UG7u>_y0MjDWOg1$J&jr>VIBmg(QmHRQYz$Qnyk5%X?fs?8GpydAx)Qtf5bcM*jF za2kmCRn9b0SnHr%tOfxPD`!55v{1HW6#o@Fg8dw2gO3-unk$KCIf=WfAQPXA#F+C! zEoJ(GYwe0+-x`~KEh<5T<55?zF(>+&+C&PmbONMt)sX4XoIWel_uk9CkkhXJ9d{iE ze~S$M7X8_LN{V2YfIg|5aA&))n}i%=!aoDZ-dI;;1CX1dQ1&S!zGce@?2n3!NV-Dd z3|J{`ArU+!;0lOf&p^9y@Kk1A6VKrBqn)z7XiJFRWw6@HuB+@Swm92}t$H~I9Hxre zpK!W?8*v#v*v72P#9AkBbS~=L68=2hTgy#1Xo}w2>+s-x=Cun4Wa3^s6QS<(YK^`L zH7Y&2t8VwQljW(UOwESK3h4Rw2*YBEIiM?=$twX}6x7k&Lmg$TvmTZgs9d5}frh?x z0W?{)3y<+9D?tQ%f|;Dx5<2)YXI)5)7dZk|!DT4$k@7h98Qc72`mdB$RH$H-Mhy19 zAh;pn{vfkuo4;J|aWJygK48QT7z<9Te!4v(=W;~6a>Um{4==_Cdt;33fifCht${$;ph#X)5q5~l!;j{ z+&rVK@a@7zST{X08>%-%rt3qGSEfaOADMnIGQA}-y*V;H5t+U#GQBM_y(u#NKxBGr zWct3y^gWU3dn42L>ms_&Px8s~ioPA%wIU)Xw zb{y_lspc=>oEZOJJI)7`x}Gc9IHp|PB(FZPYccBE(Y6w8&==5p#>RF)yNhU3zJQh= z%S%BEEmBu~0VN~$iOeEk9C#4AR8@TerCaQ+RFpw#^%qe3%4Fpf`&nAZgIUk6Gk8r9GRrsb^liigPQ6gH=CLIqPv8)+ z3BAvXXW`JOZxb|u2H$3ET@^!Qp-1RTXqpQ(M-w8WBh~POV#;VKHsV9at=Qdwv^ZlL zDcyh~)UHHRL5(il?VpOnO8%)+D>Jdh*ka4q{oZFjt9yTWdOSP2v%4G+X!O<(l_a}R zsXZw9K37cSG*-DP|pamc$RwB6@uM`QNfN*B?vv?OnmgFqJ%k`fjkw7kfBiidlnItGh%k^7;1LRT{ z@%aOps|w;JZZBi^3S~)W!yuaKSNi}c*LMlk-toR_6T;Y#_G2VsLz-vA%k@&krtTg5 z>1taDgS830UqX(z!LKFcs1Mr^f&|1W72DNMO4I?-EDq=gCA428`F{JfM)f`kqJPNY z4c8_W0xon*X9I2^ItMzvs3j{e!?RI6Y~^6Mtgp9%Te7}3rzg!48|!NrhH#{OW8x?FX9zF)TTdF&D>NBsXEuXc(9< zVn8Tg^u_2QGg1-NtOi^~W%5-dg1r$&?%4>(=Ww)|)in~^%Fvjjl>&<2m2N4ClGhUcYyv1 zp?artx9OW)a@5h;QNh46{W@t%y6*@W?s(!xcd?5;Mc_`?#Inz$mwXGEp?jb&$UOC$ zJ5TYwF=8Fsr!Ru(2G!=ccWwoq6*y;T9JaNwtK|Hw zIf{HKR$PVxSCNKpLLcv7P8XVDCF^HnRslwO3EljlNn3TUV98PCtL&Vs20B=;IatR{ zMBj)_fF`1Pm!m14L56BApPt~;4Sa%_fyT=x(6N*X;0f{`@>X24yBIfKWUiVJ6(6WJ z^L7Kbsp|RETMgsw8dTS~=H((7(BmLhIZs`#TG5H(#T|@X*=iRuj1M+%g%|>RdQlo2 z>RzFzJsj%V5UD*V1lfcg?1CAj_&?YJ;Vk6XrDnrUV82#ksxCvIeRb-SkTVI5lF&h! zcMj^a5K0+x@2zCQcHg=4Co}8}SN;f=y}odko-(^kL5XB`fu|fyx0qKj&9v!%f|!)~ zcyVHd{ZGmqy8zwF-NV~^vEAxsxIJz6R4lSM++c!ockdn*Oxq;es)s|9;5gfh){*9y zZMq7#JHZe}aiz z7m^h52Z1ohdNnjFlp!($L&C2%fejETKY;L|)Sd_+k|_l+R0(#ac#-KIJTjfyJql1X zc8~t1dvvyeCZxqb16|qSa?U>o$VS_SIY$DvsdE|vDUF)BqGO|0Ok&vC;kq256oY2C zd11S67`C?xcSn31xx3}t5cTzu7pmk(eA}YFf{1Tx)HkRs;@cd3FY1FGAG&ly^*-p- zrMn)FejF*?6Di#hDc$?{vE~Z%AQ>MdLveSl6wdpja&?zCEea!h+4W)ac`=_GMb)s_CSJfj1da*+3ca1xJ zJIE6~4&VJkdO>w>%9Dt%i59jDsD8=NHr-z$F@M4YDA1N#paCLlqQ1=$-`c2eQ^dCpI#R^^Kq`glN>R~0c8}&v7ryh5C@V~nK2`tUfAgP z=s=Ofk%Gam1s714o5Ziv@fEtwPGjueC!h&Lc3!8{eDsMKcD5!qfku$nOH?jnFR)8s zVt?<%4pw6so1Yv}z|xr5ZBA@=wHC1f{m@DdC2Ts_J|yBI3vW0vKtYbPI(b)d$nL_+ zlp>zG-JyA=W$PL{9d8l4Vdz9O)kLILjY5AS=u@~2D=%*-Z9`+Df&JwvZ4PugPBBG` zr06Lr_+A7yBQ#jYu(jK~#!AEzw7BdG(bbpVl=ZA}lBx1Xr+Z+eYz&^u6HvL^G1D&} z+%ovnhRhxS_VzxLdE$ILbekVZ55Jrqj-`eEh{GqlLmA<}pn;CO2YBDzD?Yp(em5&# z`YuL#^d*}oE1EIebaa|6gc7u^vbfwIseU+8y)^>!TJ`2g^`^)RL6j;|T^p&ck5sRU zRIiRyuZg^HD}gU?3nWs#E>gWVQoS+q0(~E}?>XU5qm zC+1@F5St7=Y%lJfS&mrW!)Q$ie;Ohhd|Ul`7p#@hmZFLcA@6osgJ(im#|9%MS{7Rf z44opmZ1!VmvZ0*rZ8|}Xk{V4{wU8K}L9#@BTd83t`1pbN$o~%>8+@BgM%PG2REu{L zTt`Nmm>1Rz-)pXh>D2zZqN<7JgnB5!@AkY|&bn5$j#Joeg9 z$7VD!C2q_}A+_3ox47Wb1iZ$8A8^4QfRmw3Y8|Q$W?X%nG)9AOqrVbTZc{R}R^JGF z3mN3Ce-mQ8=ziALTepRRA+)i6o36SBC|%xBg>LkS zn$7ww2iChCmS@A3El}I$qS5JF5`8ODT~k@WS1m;+<|c=y>EFQsXKH>YYkMiqrqzVU zdeTC@q9vZp!ndF0Om^hsNFB!y(gCN0OjnFXlYIOB~Jw3|LAk;qtOf`;N*4W zW5GMc#`D&n&Dw1t4W`d>;m0%6i5`qFkDLvPO!P>~87{^+B#BPUOu?XOZL=QfVw_@A zz3)EyNMCUU`M5e-u`wB1lib3Nl?<&)hU$}{+T<3qFS-d@!&?1a*gs6wcUYJjx5^qo zABOZX(8mD9-pw?MV;_VLgh;z&p*p++y++n9N3k`yDpetBXjG~GCGLp_%*U-iqBBZ3{6$5dHa?*nyL6+IYaL@CK$`Oq2_GIW9;RgdCcGf zWB}2DJWeKXD@T3sGpxpF5(?N8x)e=W#fl(BNxmeZj6iouXMq*M$p30ii%-wm{4WU z4cO?1UW|ojlb&viiK<1|`G{6D%bBY^##SR{zg<9tKxxuvePRSk)u?h~*Z;Xa!&jZ= z$`QUi5=T#^`%#8aae|YMJ_W;g5KF@G8+!vA>tEjp|_XgN9U&`)DRbiI1+#{%E=>RBy;{Ty@qbyx!S>%nf4z+T4e)e9tG zFM_X)2F`*jfYhm?20XE0qZLQmrqwdl&7Hj5`l;uA%XFBiZ^q#+wiATtDkr-n*(Q z;${)oS>FF#a8VXIf;8*V%TXOP)SVc5;nIVc1KYx-O-WgQCG<>tfO_k%lYz_K&x1%u zOJprOL-tZb!(ek|;ahBoQ;tX!L3^RjYYl|@7>s-+tA>|nZb-4VB1URN3onYKicER zTYra>5Ir%W-xVf(Az_W1aHBKuaL5;B!x%~E(v_y(Re%|;_OZ)VHAJxB$&}FbHb<-a zJ6NAMw7N`;y^C>a44Q8vFSTn9I?paXt>V*mKF#LSWkxH z@!w*Qwkp^UbN%|Ri*1bj)gF50@>#5=bQ$*?S<)ykg*<$ ztCRaGM2H%ifJa|#)22~G)r;w-5ady}*k14f+FqNUc?|^)4#0-IkUMyf#+va+wG-U0 z?8*hBN0z%)m|%P$NLZ1xfo>>odtD|Xdu^}fEoXa}H}jUiD`54NN?nZ^1)FBBvHCZ~4qwDlj`>B-97o@L zUThV~pl1aa0n2YnkG>A8McwYI<>XJonDN@+Pr=1J?=!<;>^L0EnIAbH#*WFf zcKrEY**dPdI{MPAb`y}=k9vXkax75OU)C9|P}bv@Q#dIN6#YCEJ`9kmk(3I<(U+mK z+_@M)zFi~-W$DAiO}+e@Cjx}XNy^VI-_?zyK)7;+HbwHMUY}?7rBKGl4pgus>-R$yu>#qbHqeCfxQRd%6TEH_v z%IvKjjY!cV&&9)bb0!}z&D15Mn5Yfw?qV7PLx}*p@JY~^>?~_REoShk{8FkX^!-@o z*zxNb-^9KzA_K3sHT$W>paau5Es%1Aqr|qJcAl%gnTBE;;_->c@#_@)D6Ntwj1PK~RksG+LyV@p-Wv4Ow z+=ZwaSEHs~OQbYDl!i*7t)e}9A!WBM$Tv#B7UV-AyPd-Z%pygOPgHFE_V;GP;Sp~N zYN&3;UPDFV@#vwlvdXl_%kYwu$FV*{TF7ox^1`pGBv$K~{ZMMXvlvf97Lk2xu4jSc zH)3O>`9VKkl7)vB>S-!(p_N+(227S5+K|InZY(_J<}i;rOhXRwb(P67d&4Tv4^q)m z4_7W}(Fe}MQa&`*K7L<9V5s7v3syL z2Z+yEn2e}P)Njf}&sn<>->3f?Q-5LO>A#PZ()=N6Yfd?i1)qk!=+QNH2RlOz3vv|v z3L_Q!rg@-)DeojF8d@fz;~$iRY2yFvMD$e~81WkYpO@RTvQ-OVzvS7Ma($hHii3m2 zA?9%f^56tSIZ=t9J$Mt-6V3YT5ypgM8)V*^Xp_S$P;NlF_-hTm96y!Xu#-_&wHgtz zNtjX?SFS&EVvuGZ(_p`zX%)v$u@(*JZ&UYZ>hAct8j~89#C^FCO$qD#c9{b~>I`7qFUq8~fnMs3F1sLNEf zPC8D@T(meWZvjIFMnnm6sr1ZH3eos+q4lJ*0d%_C zbnxp>R{U2gh-ixSzg5`$@EC8X_!D~mbQ_edYJe4wb3!ym_O4t&QB>I;wtHdc6$^Wr zKL6W@@*P0sp;>V9<03;pf3urFJZyiWH7rT`(L32-p@`|HpwX>1T5IGi{x`g!yaRxI%>z9SLcsZHryz~?kQW{xy? zxVkY7FWxyN2b#IJ_C^q^OI8)btGZ$Ot}E2uUQkk;ACmIc^Ylm5x2qwvKHQueZ9_z8 z$0Pnn9(g2r7cGZIww)wM!UFv0orO*;TsVy8bGcjLO3vlLCPTfoZv%m~^w#bY)NO_{ z=ewxWfQlKs$hQstHq^pthz0M~x)|pJ!)SB>uW-SA1sBO$`pyW0vc9rDD_XG~* zdjijbHU%SUqmV}T9zyL3PI65`tPhCsDCU_+gb2Uh2`$&O(rVD|Tz3g`>;N!wPjd=J8;BYIbzQL5h-V;B#2?AI2lXqe*c0qS?+dJYG2JgK za#DSZsc?J){otTp=@5%>0tOHo3K)!zu#+7je;(Vk_uyB8fw0CA!#*qz^mBQ$NnKY` zI@BqnhOtgY)OU+2u<-*yuCr*0HL{97K^Cpv8k+*U%GLsy?#8r)&Iu<^^)|eMGF(iv zqS}kvLvCb1?xIf_O)zf;775~+iEiz!y#S3CU#S!%Ozd$aR0+t$t!dZ@jkfsBZ|Dq1 z#}p4>mC2_%V$Hx)e82FrS#4ztj0f-79BU8==&6!rPW)Pe3Q&xAe7l&AOZe;)zBMVu zgwMl*!ouFlm{<9oh<#AdT{#PJIJg9 z+!#Bc{X-bA4J{KTV4r;-DFJ(z>?{e`exvyaL^&7AF5MK&Z)T>OjHhTRbj|kP7wqt3 zg9lS%*o)ntA>7*@&}A5j81c?3Xc2;`Mx6n!O>Zn(wRXx(h7NR+^FCfd~;1oR=eW_$iSRPICES6s%HdasH}C_V zYD)Y{Yu}w2=+&Y$Za+tcuxbO<_+qTqc>IMDy4`kI_$6kwWhV#J4_rban^2z>AasUp zHbfm@Hngkp*l4>NeCMbd4ZMIp5sibEam|I_I}5$oF&9=NkZK|1PIFiNH}Fays3o4= zr<;bFj%NSrUKZq2YDdc#pLIX9Na>zKinhiX3(X-TAz|~e!SjU2dvBIqnfeAN`T{kK zl|2k<8!~MkX6va=bYE4^)bAp?GDBZrgT3{u0O-WSUbO$X2wPGAcuu*_wjp@866>G` zIPN2pqW7`$;k;7a3`}+nx65zEagV$u`damc<_OETRU1kdpQX0)HjP4en{@thklGm6 z@k`WRlrMgPF*g;e0Spa+{}kqlbD}Nti;9A0Ebz5x3<;ckX-2H>foV=;VRw~@=`WxU zVXYwNAnYxL`2&Gqe(-jxo{0b_8GGy>=jYhp?Y#UK!wf$r0ee}cHKW~Dw&EkI8DcN< zTyJOQ*voF0%wm5cL(_C@p&jko%ftjW*Gc7?z%EBJ)K_+YX##uwT+>4y0G)Od*q&iF zxeg|YElDP)3DR+REFLUnWsuBjU zDga_v0Hu9-pFaSlb~k$Ohqz5OfRS-9a&bvlgKCsTKZw3~RTc<_N29r*H00p70g;9o zR9zGek9DDC4)ok;xELu6?u8DtpiH0VJol|jh91Q^n6@xFMlUtG7PlOA18-UCVcgLE zP=L|?X5nvkS7AI0L<=e3J|KgmW1_dSWD#u8qqL2LC4a?Iwu`(U16cTW(LIxa=dD|X zQ1lKyhY$7~+cUI0dglxT3>oxIPhpRUnjOglbW7Xp z*rs>SF$M9~--INv>{NaWX2;=s9nm-wP~jrv65HdAx6MGhXm;hdvM6!= z`tVy$>L#`}ty{jklKbnEE0?3lHoE>WvX9Z)Rd>k>zF>4s^ zwt+J2W_d@4WPh3MRF8))Rl)64EOPX&D7lSZfY+Mape;5CT_<~IO$pe91T=NBlmh+@DYH1l?DtJ(NF2?edk`a)!p>ovj*HpJ(EB-JSgB$p zv(2Etc+=ry*hwZQMmM|3s^-xYibO1<{$swWY?Tkio+8EO7Knb&$v*M~mqMddZ-|%p z&8cQgwFA8{_8hWN8~C(|Phu*46itnUk&5^ z5mc^3+V&Ew=JYU zl%!u~Aq^o`EToQ2^v|avCs$~uc^Psnq=$MK5xUzLC^6vhb}&fMvg9*tRz28RrkrE| zwvDu>lprV83cdi9t*k8vwYveRO=R#p4R^3H%lsI}`VaF>+brt_fdPKfkorrcXUpkE zClcui5Ho80hp9sEddvh}Lf3^~q|ma0S0gC}mp(MlZu2XnBH7}@%A^b72XAbmRc9i{ zvg9VoDc}I_q1>tw=_a01yW?k=;>NB)7b)YEczCJ8s z>+5iw-Y0IEO`@{X<3kpRaG%B-44}vF!g~zxThQXpx>r|CwwdCr7dMxR6#Py$YWBx* zcBE~9{g4j8W(666x-L_tZGe3ZFY2&YkWWFXM1A|vy&!hY>j>b#d%?He1Y&@_8^3N` zg**lArUy@Kx4;JU>83#Mbs^O@YS?e$QG8FH#{(rg1+t!FXW*^B zm#C$vEq}-AEBVuc3HRLF@RD!)=iCp>afq_5UH|S^UGP}|!x}poTgNyawlkIn5-yKU zaM99%My_~kdBTS!_tt)dCmtx0+Qw%)8NCY%Vn*FcGwL?8{sKRyy2Q3f9yElr9bE7O z0=5f&x(mKTz+ArrJI4jzAmD=re7&3dOn~uAjWD`;y3pwA5u>Xo(_3eZl=$gmScA%R z#if+3sc%Pk^;$H-shD$Vbp04)qNUBL?bU3~6~lyhK%YHyY{TKih2^Z2d)`C8jh^oG_(%YoANAALcp_5sY9))ja{G$_reA-xfE-;H-wy zT|8UbthbC8Eu|2K$%g5Tc$?m?C_IIx%I{d1Gf?uo$=+J_2iq=L-54{|vR0n&iGA&% zOOO*(-2lck&BDb7yvhdiw2;YvfXV+9H~$gHpF_-BdjQ4u)(@8U-;c7jvUpb&+0peL zsRQk_wksK}ryD0Y(eEJ(_ENlm$8PMAGKq3B|DXYenD^`9oq_om!%ikrHSMs8Z}T&H1EwuKDK4HS${g- z!D&Y880+kBfbb>kIic7_uYCdN-ufJ=${rcMExMlDzp_5x2xl_wMaTvx~#bK=CV6aMRd7NFOWkU_~Y_t6w z$XJ@~Swe|u);*lM*4IcODA(#Xz*L^JC}`clfz&_;^K{Cu!t2e@1yU>rZz1Sf4#Lgt*6Aw9w=cC$ zcP%y@%QYNM@`<+5(K>z3R2!@P^+}F(dU^?>zF?jHuXbgmlXZHEv!c&7n*$xK(;qwO zj&7ZPZ86JXHu#QWovyq=<_Ft4y&Cm4*6BP+23{T2I$d^}UAh05b$SryJEO1{oXD=) z_U~G!&v6O8dx9bK<<{xr`rFk=u}&|W$Pv+Qoo>c@*|ko8z{RuuvTSkW6zlX<@Je5_ zh|qM$6{)||*8+6d9l5;aQWyLB!LyT3bETeqnhSOP zXV`MEL>}1zICPo-``HOmxZuJL2;UI|%vMoS#&0Bu%_g(5OZ}S2JYC2Qtuq zY<~o@;(Zu6e(doGWW>8M(0gp}5MG4}L!c+#BmCijntu%N)~-QGqdN`Zmtr~L57Q#0 z@N^7b$@V){tSe7**~>NW&*En7j6-;M`BZg_#KPMA$_&GWs+$c&>!%#Z)izF<{vX*r zfTgS?dLNfaoD%PaXzpZKonQ>B*O>*wt!$K890A6xs*9yV#{I^uI$kW{u&!<;Ub}Ub zn|1Bh)n>=K3M9P=f?B#$cjduU5zu#oq*zz&twT>P5X4&mKil`2mo;zIe?`qxWaUE_ zII=Q1umBzy$$^`(W0)McPrkRwcOQW_%JUBS&IbgiWcjnNG%UUkw`F)dpB6k1#-WQa zJ}H@!p|0{vC-O^%=wiS5s~0ySK~pkB=#2=$9{d%~(covD;G2q{?i5R}7uLIE@VM8~ ztnuN$rG<|8_2yp2N&z7xHG`vR;6ieFNwzsMQ^5wxXbg|Dg6HtpP;;>_QJND88?9{xqN$S#Mk?XufRI^f7pBf@TjV5@q3b)Bm+#C0fPn&5+o=Us*!*a14@tt z{1KcGnGi9-R*k14RSGi!dqol_u{j*4rMK96+uBOeUTtl)RRMn|1e1WMpcb)E8(VHY zacGT7A!uIa{j7b?OcDg?_df6Qyx%{{L(ZHZd#}Cs+H0@9_S$Q$Ej%h@)8IPDBl3C5 z%JUvUM*}f ztxLr50hE;FKITBH7((?QI)ml6wT4>|bzSZ+H(R8z>O(Law>#8ndRlwqu|X7qg6RuS)FElVs%?D!#KVsbecF_y{Y=mRn%KI!uT|nN%?Z0 zYJ4gmLAqM${aIh=5yn)KwcJwM$d4S6ZJ~%Vc2V!sDLN~m=0w4?B$TJ|fpkVtK`a$d;JOs6+ z9~PL?rO0YJc|bp?PDqn+f&+`)5B7$U>IdQL977ITzc4f|fReHp?FEO~FZNwqSz%5Z zCRCBdD0CNftaOEk;bA8XuiZ7)Vej=Q=JX{%^S=Nz<2az1Hc;sU*MAHI3swr=gdhWu z)A>d?tAe^`Px_d;pYGk9GrShN_{>^;bfh))+Sx2F!+%?{n9g=Zx>K(b&yRw`6C`R- zt$q=Qe5Fafi7Nzwj;P+6B_s)c6mt`d?EWY;{xR9g4&{)TkV?_4tD)qMNv%d%ww|Ks zgY=I%U>Tv=a60d%9yrpQ$js$!yjR`%xVwwHf;WR{RYyKH_86VFwWPJa zpQ@L+C+)(K;xja2*OA~#=MG+RplP}3@j$-2sFm(x)aN`eVcaUTN7GqYsL7~fDBs(< z&nK7a6StnyE!@$&Im5fDd6$9j>CuJW#$)Q$+*I$TdiAcCcOUZZww8s?PVeTqu7MwR z^WhsUg|IgDEq&m(XVka9*9@_~xd(pxFZJzrjX7vLJx1%1U4196VlStg+er;IQ#7^Yq-0T_haoRkq6~mGvRlXEQZj5p+2Jh#Xz?PaDEiNi!Tad~S5=NM^xF?J}7S_nTAe zs0LB^q$&C4FVS*Dwq?hx19R-)*|IUm5ck2}C*h$=aO;+p5sPt!yKCg^k_F{5#p8o1*n>)v*aMRi z&}3i3tIGFi->S6d(=e&5&|Uz9g}nnzr^+7Z+So7_O+{J7;BQr&rD0Le3J&9L5WVP{ zn_6XrGwm7V9l*zaej?;mR0J&a_1Aa+`c7Kk_W;Y7L3hagI#5}%k&cpJCC943h;+HTxk7uj}b-sTO${!2JsYf?sl zFY!wRA?8cAI>p=EAm7V;1#eFBqRTf{XYD@93VB{Zi=R^nC26y*99wmL^y*Y7!Ei>} zQfrI0hW`oJN$>9dd;x2ZMF_v7y&;kI0+7s_RF`F(EYi;gcJx}zfeH@S8X1ue0JIAL z&!nTf<0;c^F<4Q2xu^-G8|3(R@#k}!a$p9XF*IaKXq-Op`WBn$#){x5Yl%Z_1>cJU) zKPbcD$G?yvL2uGYib4AWm1ZFnO5M+62}�)Y*&kGlbqs`X=>Ip`arWbKQ# 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 literal 0 HcmV?d00001 diff --git a/installer/MergeModules hide/EcFolderACLsMM.wixpdb b/installer/MergeModules hide/EcFolderACLsMM.wixpdb new file mode 100644 index 0000000000000000000000000000000000000000..c8f3a5962a2f635a63747375c1d7edec0df32882 GIT binary patch literal 167273 zcmV)CK*GOGQ$t1o0000!p#cB@0000i00000000030RaF3000000000!0000700987 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

B}H8Z?3a? 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

Y}&pijkrWM9UG^vm3qEjw*2c^1JR9rkN`#o2O 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

lpJM-6UF0h`0-?KtdlK)w3ob)-cT1gC&4OJN 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 O8Q|z4`0Rl9!TukIE# Debug - bin\$(Platform)\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/PerlEcMM/PerlEcMM.wixproj b/installer/PerlEcMM/PerlEcMM.wixproj index 95a3133a..333afa2d 100644 --- a/installer/PerlEcMM/PerlEcMM.wixproj +++ b/installer/PerlEcMM/PerlEcMM.wixproj @@ -1,7 +1,7 @@ - Debug + Release x86 3.11 {d6a6243c-a7f4-4174-80c5-5efd39c29d5e} @@ -10,12 +10,12 @@ Module - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ diff --git a/installer/PythonEc64bitMM/PythonEc64bitMM.wixproj b/installer/PythonEc64bitMM/PythonEc64bitMM.wixproj index 32d43207..5a4852ed 100644 --- a/installer/PythonEc64bitMM/PythonEc64bitMM.wixproj +++ b/installer/PythonEc64bitMM/PythonEc64bitMM.wixproj @@ -11,12 +11,12 @@ Debug - bin\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ diff --git a/installer/PythonEcMM/PythonEcMM.wixproj b/installer/PythonEcMM/PythonEcMM.wixproj index 5bf9d013..832cfacf 100644 --- a/installer/PythonEcMM/PythonEcMM.wixproj +++ b/installer/PythonEcMM/PythonEcMM.wixproj @@ -10,12 +10,12 @@ Module - bin\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ Debug - ..\MergeModules\$(Platform)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ obj\$(Configuration)\ diff --git a/installer/TECkit64bitDllsMM/TECkit64bitDllsMM.wixproj b/installer/TECkit64bitDllsMM/TECkit64bitDllsMM.wixproj index a7d08f1b..304f7e85 100644 --- a/installer/TECkit64bitDllsMM/TECkit64bitDllsMM.wixproj +++ b/installer/TECkit64bitDllsMM/TECkit64bitDllsMM.wixproj @@ -10,12 +10,12 @@ Module - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - bin\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ Debug diff --git a/installer/TECkitDLLsMM/TECkitDLLsMM.wixproj b/installer/TECkitDLLsMM/TECkitDLLsMM.wixproj index 70f39a72..d443ce1e 100644 --- a/installer/TECkitDLLsMM/TECkitDLLsMM.wixproj +++ b/installer/TECkitDLLsMM/TECkitDLLsMM.wixproj @@ -10,12 +10,12 @@ Module - ..\MergeModules\$(Platform)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ - bin\$(Configuration)\ - obj\$(Platform)\$(Configuration)\ + ..\..\output\MergeModules\$(Platform)\$(Configuration)\ + obj\$(Configuration)\ Debug diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj index dc86ce84..af2704cb 100644 --- a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj @@ -1,4 +1,4 @@ - + @@ -61,7 +61,7 @@ ..\..\..\..\packages\Azure.Core.1.35.0\lib\net472\Azure.Core.dll - + ..\..\..\..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll True From d6ab7fa488cf9b956c985521451a8fa72437f807 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 12:18:11 -0500 Subject: [PATCH 037/113] fix the nuget package build job (I think) --- .github/workflows/build.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a6f55154..368a39c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,9 +45,14 @@ jobs: publish_nuget: runs-on: windows-2019 + strategy: + # Keep building other jobs even if another fails, to show what _is_ still working. + fail-fast: false + matrix: + build_configuration: ["Release"] + steps: - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' run: | xcopy /s /y .\Common\* .\output @@ -56,11 +61,9 @@ jobs: shell: cmd - name: Create NuGet Package - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - name: Upload NuGet Package as Artifact - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' uses: actions/upload-artifact@v2 with: name: ${{matrix.build_configuration}}-nuget-package From a77c8657f5caef9ad962eb5b7a4b8f5405b35e2e Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 12:24:02 -0500 Subject: [PATCH 038/113] but don't run the publish_nuget job until the build job is finished --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 368a39c3..745466ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,6 +44,7 @@ jobs: xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ publish_nuget: + needs: build-windows runs-on: windows-2019 strategy: # Keep building other jobs even if another fails, to show what _is_ still working. From 772a5e51e260b7ffc9be8910a5214d03d038c348 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 12:52:03 -0500 Subject: [PATCH 039/113] can't have it be a separate job or it won't have access to the data we copied to 'Common'... try to limit it to just the last permutation of the matrix processed in the hope that works. --- .github/workflows/build.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 745466ef..c7282020 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,19 +43,9 @@ jobs: run: | xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - publish_nuget: - needs: build-windows - runs-on: windows-2019 - strategy: - # Keep building other jobs even if another fails, to show what _is_ still working. - fail-fast: false - matrix: - build_configuration: ["Release"] - - steps: - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) - run: | - xcopy /s /y .\Common\* .\output + run: xcopy /s /y .\Common\* .\output + if: matrix.build_configuration == "Release" && matrix.build_platform == "Win32" - name: List Files in Repository run: dir /s @@ -63,9 +53,11 @@ jobs: - name: Create NuGet Package run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} + if: matrix.build_configuration == "Release" && matrix.build_platform == "Win32" - name: Upload NuGet Package as Artifact uses: actions/upload-artifact@v2 + if: matrix.build_configuration == "Release" && matrix.build_platform == "Win32" with: name: ${{matrix.build_configuration}}-nuget-package path: ./output/${{matrix.build_configuration}}/*.nupkg From ca45c4edafc6c23269c08be5d9631b15d843712d Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 12:54:45 -0500 Subject: [PATCH 040/113] fix syntax of if: statements --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c7282020..d56d30a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,7 +45,7 @@ jobs: - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) run: xcopy /s /y .\Common\* .\output - if: matrix.build_configuration == "Release" && matrix.build_platform == "Win32" + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' - name: List Files in Repository run: dir /s @@ -53,11 +53,11 @@ jobs: - name: Create NuGet Package run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - if: matrix.build_configuration == "Release" && matrix.build_platform == "Win32" + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' - name: Upload NuGet Package as Artifact uses: actions/upload-artifact@v2 - if: matrix.build_configuration == "Release" && matrix.build_platform == "Win32" + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' with: name: ${{matrix.build_configuration}}-nuget-package path: ./output/${{matrix.build_configuration}}/*.nupkg From 6e0f2e03b2f8d203a239a95fbb53dc728e66e4dd Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 12:59:39 -0500 Subject: [PATCH 041/113] switch to making the x64 (the longest running permutation) the one we use for the nuget packaging (all the other permutations should be done by then --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d56d30a9..81f44ee2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: build_configuration: ["Debug", "Release"] - build_platform: ["x64", "Win32"] + build_platform: ["Win32", "x64"] steps: - name: Checkout @@ -45,7 +45,7 @@ jobs: - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) run: xcopy /s /y .\Common\* .\output - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' - name: List Files in Repository run: dir /s @@ -53,11 +53,11 @@ jobs: - name: Create NuGet Package run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' - name: Upload NuGet Package as Artifact uses: actions/upload-artifact@v2 - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'Win32' + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' with: name: ${{matrix.build_configuration}}-nuget-package path: ./output/${{matrix.build_configuration}}/*.nupkg From 4b3f4a0dcf2cb984bcef9a66512075d50469688e Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 13:17:32 -0500 Subject: [PATCH 042/113] put in a step to wait for the test*.dll file to be generated from all 4 of the matrix build permutations before going on to do the nuget pack --- .github/workflows/build.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 81f44ee2..2e2aa8a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,24 @@ jobs: - name: Copy files to common location run: | - xcopy /s /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ + xcopy /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ + + - name: Wait for Matrix Files to be copied + if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' + run: | + $timeout = 0 + while ($timeout -lt 5*60) { + if (Test-Path -Path '.\Common\Win32\Debug\TestEncCnvtrs.dll' -And Test-Path -Path '.\Common\Win32\Release\TestEncCnvtrs.dll' -And Test-Path -Path '.\Common\x64\Debug\TestEncCnvtrs.dll') { + Write-Host "All required files exist, continuing..." + exit 0 + } else { + Write-Host "Waiting for files to exist..." + Start-Sleep -Seconds 5 + $timeout += 5 + } + } + Write-Host "Timed out waiting for files to exist." + exit 1 - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) run: xcopy /s /y .\Common\* .\output From 962108100c012e754fb40d337c07a0d67a443698 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 13:23:09 -0500 Subject: [PATCH 043/113] fix PS syntax issue --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e2aa8a1..f972181f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,7 +48,7 @@ jobs: run: | $timeout = 0 while ($timeout -lt 5*60) { - if (Test-Path -Path '.\Common\Win32\Debug\TestEncCnvtrs.dll' -And Test-Path -Path '.\Common\Win32\Release\TestEncCnvtrs.dll' -And Test-Path -Path '.\Common\x64\Debug\TestEncCnvtrs.dll') { + if ((Test-Path -Path '.\Common\Win32\Debug\TestEncCnvtrs.dll') -And (Test-Path -Path '.\Common\Win32\Release\TestEncCnvtrs.dll') -And (Test-Path -Path '.\Common\x64\Debug\TestEncCnvtrs.dll')) { Write-Host "All required files exist, continuing..." exit 0 } else { From cf37bf9c633003a849302a519faac95089c0ec27 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 13:38:50 -0500 Subject: [PATCH 044/113] added debugging info --- .github/workflows/build.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f972181f..f6229e2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,14 +41,20 @@ jobs: - name: Copy files to common location run: | - xcopy /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ + xcopy /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }} - name: Wait for Matrix Files to be copied if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' run: | $timeout = 0 - while ($timeout -lt 5*60) { - if ((Test-Path -Path '.\Common\Win32\Debug\TestEncCnvtrs.dll') -And (Test-Path -Path '.\Common\Win32\Release\TestEncCnvtrs.dll') -And (Test-Path -Path '.\Common\x64\Debug\TestEncCnvtrs.dll')) { + while ($timeout -lt 4*60) { + $Win32Debug = (Test-Path -Path '.\Common\Win32\Debug\TestEncCnvtrs.dll') + $Win32Release = (Test-Path -Path '.\Common\Win32\Release\TestEncCnvtrs.dll') + $x64Debug = (Test-Path -Path '.\Common\x64\Debug\TestEncCnvtrs.dll') + '$Win32Debug: ' + $Win32Debug + '$Win32Release: ' + $Win32Release + '$x64Debug: ' + $x64Debug + if ($Win32Debug -And $Win32Release -And $x64Debug) { Write-Host "All required files exist, continuing..." exit 0 } else { @@ -58,7 +64,7 @@ jobs: } } Write-Host "Timed out waiting for files to exist." - exit 1 + exit 0 - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) run: xcopy /s /y .\Common\* .\output From 5385a2d84c82754a4458b6cc95ce18ca450fa5b6 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 13:46:33 -0500 Subject: [PATCH 045/113] try 2 --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f6229e2b..e1c6312c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: - name: Copy files to common location run: | - xcopy /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }} + xcopy /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - name: Wait for Matrix Files to be copied if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' @@ -59,6 +59,9 @@ jobs: exit 0 } else { Write-Host "Waiting for files to exist..." + Get-ChildItem -Path .\Common\Win32\Debug + Get-ChildItem -Path .\Common\Win32\Release + Get-ChildItem -Path .\Common\x64\Debug Start-Sleep -Seconds 5 $timeout += 5 } From 6d8957edd583758b656cc7b4536c74b486cc7e00 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 13:51:12 -0500 Subject: [PATCH 046/113] didn't know that would error... --- .github/workflows/build.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e1c6312c..b94dae2f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,9 +59,7 @@ jobs: exit 0 } else { Write-Host "Waiting for files to exist..." - Get-ChildItem -Path .\Common\Win32\Debug - Get-ChildItem -Path .\Common\Win32\Release - Get-ChildItem -Path .\Common\x64\Debug + Get-ChildItem -Path .\Common Start-Sleep -Seconds 5 $timeout += 5 } From ce421a22fd44cd2b9f3a6424dc823fa1ba60f354 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 15:48:41 -0500 Subject: [PATCH 047/113] finally discovered that individual matrix permutations do *not* have a Common folder space that you can copy data to to have it copied back later to combine them... (you're welcome ChatGPT for the drugs) Switching to upload/download artifacts in different jobs --- .github/workflows/build.yml | 57 ++++++++++++++----------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b94dae2f..2e20bf54 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v1.0.2 @@ -39,37 +39,26 @@ jobs: # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference run: msbuild /m /p:Configuration=${{matrix.build_configuration}} /p:Platform=${{ matrix.build_platform }} "${{env.SOLUTION_FILE_PATH}}" - - name: Copy files to common location - run: | - xcopy /y .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\* .\Common\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ + - uses: actions/upload-artifact@v3 + with: + name: build-artifacts-${{ matrix.build_platform }}-${{ matrix.build_configuration }} + path: .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ - - name: Wait for Matrix Files to be copied - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' - run: | - $timeout = 0 - while ($timeout -lt 4*60) { - $Win32Debug = (Test-Path -Path '.\Common\Win32\Debug\TestEncCnvtrs.dll') - $Win32Release = (Test-Path -Path '.\Common\Win32\Release\TestEncCnvtrs.dll') - $x64Debug = (Test-Path -Path '.\Common\x64\Debug\TestEncCnvtrs.dll') - '$Win32Debug: ' + $Win32Debug - '$Win32Release: ' + $Win32Release - '$x64Debug: ' + $x64Debug - if ($Win32Debug -And $Win32Release -And $x64Debug) { - Write-Host "All required files exist, continuing..." - exit 0 - } else { - Write-Host "Waiting for files to exist..." - Get-ChildItem -Path .\Common - Start-Sleep -Seconds 5 - $timeout += 5 - } - } - Write-Host "Timed out waiting for files to exist." - exit 0 - - - name: Copy files back for nuget packaging (bkz nuspec is looking for them in the output folder) during the 'Release' build (bkz both platforms will have been finished by then) - run: xcopy /s /y .\Common\* .\output - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' + publish_nuget: + needs: build-windows + runs-on: windows-2019 + strategy: + # Keep building other jobs even if another fails, to show what _is_ still working. + fail-fast: false + matrix: + build_configuration: ["Release"] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Download all workflow run artifacts + uses: actions/download-artifact@v3 - name: List Files in Repository run: dir /s @@ -77,11 +66,9 @@ jobs: - name: Create NuGet Package run: nuget pack ./Package.${{matrix.build_configuration}}.nuspec -OutputDirectory ./output/${{matrix.build_configuration}} - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' - name: Upload NuGet Package as Artifact - uses: actions/upload-artifact@v2 - if: matrix.build_configuration == 'Release' && matrix.build_platform == 'x64' + uses: actions/upload-artifact@v3 with: name: ${{matrix.build_configuration}}-nuget-package path: ./output/${{matrix.build_configuration}}/*.nupkg @@ -107,7 +94,7 @@ jobs: run: sudo apt-get install --assume-yes automake g++ python2-dev python2 libicu-dev mono5-sil icu-dev-fw libteckit-dev - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: List Files in Repository run: ls -R From aa1b853e4cec3f42e2ab9a3981242a25c10fcdbb Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 16:14:57 -0500 Subject: [PATCH 048/113] trying wildcard approach to a) limit what gets archived and 2) supposedly keeps the folder structure I want after download --- .github/workflows/build.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e20bf54..07b4a293 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,7 +42,12 @@ jobs: - uses: actions/upload-artifact@v3 with: name: build-artifacts-${{ matrix.build_platform }}-${{ matrix.build_configuration }} - path: .\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\ + path: | + .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.exe + .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll + .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb + .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config + retention-days: 1 publish_nuget: needs: build-windows From 68758175eb3b295a34227f07d330224c654acbe3 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 16:42:32 -0500 Subject: [PATCH 049/113] try 2 --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 07b4a293..ac38590f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,10 +43,10 @@ jobs: with: name: build-artifacts-${{ matrix.build_platform }}-${{ matrix.build_configuration }} path: | - .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.exe - .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll - .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb - .\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config + '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.exe' + '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll' + '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb' + '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config' retention-days: 1 publish_nuget: From f6920fff688cb3010c6ed344129d504d36272074 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 16:50:28 -0500 Subject: [PATCH 050/113] try 3 --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac38590f..c59e5b26 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,10 +43,10 @@ jobs: with: name: build-artifacts-${{ matrix.build_platform }}-${{ matrix.build_configuration }} path: | - '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.exe' - '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll' - '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb' - '*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config' + '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.exe' + '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll' + '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb' + '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config' retention-days: 1 publish_nuget: From 49467d7a9c224d27461080d10c122667a1b07e02 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 17:12:28 -0500 Subject: [PATCH 051/113] try 4 --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c59e5b26..8c4e1e3f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,10 +43,10 @@ jobs: with: name: build-artifacts-${{ matrix.build_platform }}-${{ matrix.build_configuration }} path: | - '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.exe' - '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll' - '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb' - '..\*\output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config' + '.\output\*\${{ matrix.build_configuration }}\*.exe' + '.\output\*\${{ matrix.build_configuration }}\*.dll' + '.\output\*\${{ matrix.build_configuration }}\*.tlb' + '.\output\*\${{ matrix.build_configuration }}\*.config' retention-days: 1 publish_nuget: From 509c4ef14049eb7a152ae56630b35f0e35e9631c Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 17:18:28 -0500 Subject: [PATCH 052/113] try 5 --- .github/workflows/build.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8c4e1e3f..85846eee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,14 +39,18 @@ jobs: # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference run: msbuild /m /p:Configuration=${{matrix.build_configuration}} /p:Platform=${{ matrix.build_platform }} "${{env.SOLUTION_FILE_PATH}}" + - name: List Files in Repository + run: dir /s + shell: cmd + - uses: actions/upload-artifact@v3 with: name: build-artifacts-${{ matrix.build_platform }}-${{ matrix.build_configuration }} path: | - '.\output\*\${{ matrix.build_configuration }}\*.exe' - '.\output\*\${{ matrix.build_configuration }}\*.dll' - '.\output\*\${{ matrix.build_configuration }}\*.tlb' - '.\output\*\${{ matrix.build_configuration }}\*.config' + '.\output\**\${{ matrix.build_configuration }}\*.exe' + '.\output\**\${{ matrix.build_configuration }}\*.dll' + '.\output\**\${{ matrix.build_configuration }}\*.tlb' + '.\output\**\${{ matrix.build_configuration }}\*.config' retention-days: 1 publish_nuget: From ca5da0ceeb35971c76115b7bcd9bd53168c5da6c Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 17:25:37 -0500 Subject: [PATCH 053/113] try 6 --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 85846eee..4f0cd301 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,10 +47,10 @@ jobs: with: name: build-artifacts-${{ matrix.build_platform }}-${{ matrix.build_configuration }} path: | - '.\output\**\${{ matrix.build_configuration }}\*.exe' - '.\output\**\${{ matrix.build_configuration }}\*.dll' - '.\output\**\${{ matrix.build_configuration }}\*.tlb' - '.\output\**\${{ matrix.build_configuration }}\*.config' + output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.exe + output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll + output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb + output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config retention-days: 1 publish_nuget: From 1e5b207006fe11143fc7d1f8587c1711295a1db8 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 17:42:08 -0500 Subject: [PATCH 054/113] try 7 --- .github/workflows/build.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f0cd301..c8a63ade 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -69,6 +69,28 @@ jobs: - name: Download all workflow run artifacts uses: actions/download-artifact@v3 + - name: Get Folder Names + id: get-folders + run: | + $folderNames = Get-ChildItem -Directory -Path . | Where-Object { $_.Name -like 'build-artifacts-*' } | Select-Object -ExpandProperty Name + Write-Output "::set-output name=folder-names::$folderNames" + + - name: Process Folders + run: | + $folderNames = ${{ steps.get-folders.outputs.folder-names }} + foreach ($folderName in $folderNames) { + $platform = '' + $configuration = '' + $pattern = '^build-artifacts-(\w+)-(\w+)$' + if ($folderName -match $pattern) { + $platform = $matches[1] + $configuration = $matches[2] + } + + $destination = ".\output\$platform\$configuration\" + xcopy ".\$folderName\*" $destination /Y /E + } + - name: List Files in Repository run: dir /s shell: cmd From e601811d800e2e2d7616a9308bec47b2fc317b94 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 18:01:03 -0500 Subject: [PATCH 055/113] try n+1 --- .github/workflows/build.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c8a63ade..ccdbdd49 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,17 +78,18 @@ jobs: - name: Process Folders run: | $folderNames = ${{ steps.get-folders.outputs.folder-names }} + $folderNames + $platform = '' + $configuration = '' + $pattern = '^build-artifacts-(\w+)-(\w+)$' foreach ($folderName in $folderNames) { - $platform = '' - $configuration = '' - $pattern = '^build-artifacts-(\w+)-(\w+)$' if ($folderName -match $pattern) { $platform = $matches[1] $configuration = $matches[2] } - $destination = ".\output\$platform\$configuration\" - xcopy ".\$folderName\*" $destination /Y /E + $destination = "output\$platform\$configuration\" + xcopy $folderName\* $destination /Y /E } - name: List Files in Repository From 3fd5131076208dfce63d146e79a0993e378cd781 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 18:32:36 -0500 Subject: [PATCH 056/113] no idea... --- .github/workflows/build.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccdbdd49..995a82f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -73,11 +73,6 @@ jobs: id: get-folders run: | $folderNames = Get-ChildItem -Directory -Path . | Where-Object { $_.Name -like 'build-artifacts-*' } | Select-Object -ExpandProperty Name - Write-Output "::set-output name=folder-names::$folderNames" - - - name: Process Folders - run: | - $folderNames = ${{ steps.get-folders.outputs.folder-names }} $folderNames $platform = '' $configuration = '' @@ -89,7 +84,7 @@ jobs: } $destination = "output\$platform\$configuration\" - xcopy $folderName\* $destination /Y /E + xcopy /y "$folderName\*.*" $destination } - name: List Files in Repository From 891a81e542e854bdd29c9008b287291e67a9327b Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 18:44:08 -0500 Subject: [PATCH 057/113] asdg --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 995a82f2..42e93f8d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -84,7 +84,9 @@ jobs: } $destination = "output\$platform\$configuration\" - xcopy /y "$folderName\*.*" $destination + $source = "$folderName\*.*" + "xcopy /y $source $destination" + xcopy /y $source $destination } - name: List Files in Repository From ca82f91b69706aeb990438a6d0351353bf346a27 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 18:53:14 -0500 Subject: [PATCH 058/113] this'll be it ;-) --- .github/workflows/build.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 42e93f8d..96c313be 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -74,19 +74,10 @@ jobs: run: | $folderNames = Get-ChildItem -Directory -Path . | Where-Object { $_.Name -like 'build-artifacts-*' } | Select-Object -ExpandProperty Name $folderNames - $platform = '' - $configuration = '' - $pattern = '^build-artifacts-(\w+)-(\w+)$' foreach ($folderName in $folderNames) { - if ($folderName -match $pattern) { - $platform = $matches[1] - $configuration = $matches[2] - } - - $destination = "output\$platform\$configuration\" $source = "$folderName\*.*" - "xcopy /y $source $destination" - xcopy /y $source $destination + "xcopy /s /y $source .\" + xcopy /s /y $source .\ } - name: List Files in Repository From 9dbfa3ae0c5b29b267cdf0914db7a3d42de505a5 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 1 Nov 2023 19:13:17 -0500 Subject: [PATCH 059/113] forgot the merge modules --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96c313be..4590a81f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,6 +51,7 @@ jobs: output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.dll output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.tlb output\${{ matrix.build_platform }}\${{ matrix.build_configuration }}\*.config + output\MergeModules\**\*.* retention-days: 1 publish_nuget: From dc4dd9af8bbf4f58ca36e1a1a00b58f101a33558 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Thu, 2 Nov 2023 18:26:44 -0500 Subject: [PATCH 060/113] fixed some issues that came up during Python 3 testing --- src/ECInterfaces/ECInterfaces.cs | 2 +- src/EncCnvtrs/AutoConfigDialog.cs | 14 ++++- src/EncCnvtrs/EncCnvtrs.resx | 4 +- .../Py3ScriptAutoConfigDialog.Designer.cs | 3 +- src/PyScriptEC/Py3ScriptAutoConfigDialog.cs | 62 +++++++++++++------ src/PyScriptEC/Py3ScriptEncConverter.cs | 40 ++++++++---- 6 files changed, 86 insertions(+), 39 deletions(-) diff --git a/src/ECInterfaces/ECInterfaces.cs b/src/ECInterfaces/ECInterfaces.cs index 7fc4faa9..a6e027da 100644 --- a/src/ECInterfaces/ECInterfaces.cs +++ b/src/ECInterfaces/ECInterfaces.cs @@ -605,7 +605,7 @@ public enum ErrStatus Exception = -6, // an internal error has occurred NameNotFound = -7, // couldn't find the requested name: '{0}' IncompleteChar = -8, // bad input data (lone surrogate, incomplete UTF8 sequence) - CompilationFailed = -9, // mapping compilation failed (syntax errors, etc) + CompilationFailed = -9, // mapping compilation failed (syntax errors, etc): '{0}' OutOfMemory = -10, // unable to allocate required memory CantOpenReadMap = -11, // unable to open or read the map file '{0}' InEncFormNotSupported = -12, // the input encoding format is not supported diff --git a/src/EncCnvtrs/AutoConfigDialog.cs b/src/EncCnvtrs/AutoConfigDialog.cs index 61979480..15b43828 100755 --- a/src/EncCnvtrs/AutoConfigDialog.cs +++ b/src/EncCnvtrs/AutoConfigDialog.cs @@ -7,6 +7,7 @@ using System.IO; // for Path.DirectorySeparatorChar using Microsoft.Win32; // for RegistryKey using ECInterfaces; // for IEncConverter +using System.Diagnostics; namespace SilEncConverters40 { @@ -355,8 +356,17 @@ protected virtual bool OnApply() } else { - m_aEC = InitializeEncConverter; - IsModified = false; + try + { + m_aEC = InitializeEncConverter; + } + catch (Exception ex) + { + var error = EncConverters.LogExceptionMessage("AutoConfigure", ex); + MessageBox.Show($"OnApply failed: {error}", EncConverters.cstrCaption); + } + + IsModified = false; // finally, if we're in 'edit mode' and the converter is already in the repository // then re-add it to save changes to the repository (i.e. make the default behavior diff --git a/src/EncCnvtrs/EncCnvtrs.resx b/src/EncCnvtrs/EncCnvtrs.resx index 4fe2131f..968e8a65 100755 --- a/src/EncCnvtrs/EncCnvtrs.resx +++ b/src/EncCnvtrs/EncCnvtrs.resx @@ -151,7 +151,7 @@ The compiled mapping data is not recognizable - mapping compilation failed (syntax errors, etc) + mapping compilation failed (syntax errors, etc): '{0}' couldn't find the requested name: '{0}' @@ -175,7 +175,7 @@ syntax error in the CC table - Unable to open or read the map file '{0}' + Unable to open or read the map file: '{0}' No encoding converter by the name '{0}' diff --git a/src/PyScriptEC/Py3ScriptAutoConfigDialog.Designer.cs b/src/PyScriptEC/Py3ScriptAutoConfigDialog.Designer.cs index 4fcd5107..261a9ccf 100644 --- a/src/PyScriptEC/Py3ScriptAutoConfigDialog.Designer.cs +++ b/src/PyScriptEC/Py3ScriptAutoConfigDialog.Designer.cs @@ -92,7 +92,7 @@ private void InitializeComponent() this.textBoxFileSpec.Name = "textBoxFileSpec"; this.textBoxFileSpec.Size = new System.Drawing.Size(390, 20); this.textBoxFileSpec.TabIndex = 1; - this.textBoxFileSpec.TextChanged += new System.EventHandler(this.textBoxFileSpec_TextChanged); + this.textBoxFileSpec.TextChanged += new System.EventHandler(this.textBox_TextChanged); // // buttonBrowse // @@ -124,6 +124,7 @@ private void InitializeComponent() this.textBoxPython3Path.Name = "textBoxPython3Path"; this.textBoxPython3Path.Size = new System.Drawing.Size(384, 20); this.textBoxPython3Path.TabIndex = 6; + this.textBoxPython3Path.TextChanged += new System.EventHandler(this.textBox_TextChanged); // // buttonPython3Browse // diff --git a/src/PyScriptEC/Py3ScriptAutoConfigDialog.cs b/src/PyScriptEC/Py3ScriptAutoConfigDialog.cs index 23c9f217..f5fc2759 100644 --- a/src/PyScriptEC/Py3ScriptAutoConfigDialog.cs +++ b/src/PyScriptEC/Py3ScriptAutoConfigDialog.cs @@ -9,12 +9,22 @@ using System.Windows.Forms; using System.IO; using ECInterfaces; // for IEncConverter +using System.Linq; namespace SilEncConverters40 { public partial class Py3ScriptAutoConfigDialog : PythonAutoConfigDialog { - public Py3ScriptAutoConfigDialog( + private const string OpenFileDialogTitleBrowseForDll = "Browse for Python 3 DLL"; + private const string OpenFileDialogTitleBrowseForScript = "Browse for Python Script"; + + private const string OpenFileDialogDefaultExtBrowseForDll = "dll"; + private const string OpenFileDialogDefaultExtBrowseForScript = "py"; + + private const string OpenFileDialogFilterBrowseForDll = "Python 3 DLL (Python3 DLL)|Python3??.dll"; + private const string OpenFileDialogFilterBrowseForScript = "Python scripts (*.py)|*.py"; + + public Py3ScriptAutoConfigDialog( IEncConverters aECs, string strDisplayName, string strFriendlyName, @@ -132,8 +142,9 @@ protected override string DefaultFriendlyName private void buttonBrowse_Click(object sender, EventArgs e) { - openFileDialogBrowse.DefaultExt = "py"; - openFileDialogBrowse.Filter = "Python scripts (*.py)|*.py"; + // since we use the same dialog for the python script and the python dll, don't keep the 'FileName' around, + // when searching for the latter + InitializeOpenFileDialog(openFileDialogBrowse.FileName, OpenFileDialogDefaultExtBrowseForScript, OpenFileDialogFilterBrowseForScript, OpenFileDialogTitleBrowseForScript); var scriptPath = Py3ScriptEncConverter.ScriptPath(ConverterIdentifier); if (!String.IsNullOrEmpty(scriptPath)) openFileDialogBrowse.InitialDirectory = Path.GetDirectoryName(scriptPath); @@ -148,23 +159,34 @@ private void buttonBrowse_Click(object sender, EventArgs e) } private void buttonBrowseForPythonDll_Click(object sender, EventArgs e) - { - openFileDialogBrowse.DefaultExt = "dll"; - openFileDialogBrowse.Filter = "Python 3 DLL (Python3 DLL)|Python3??.dll"; - var distroPath = Py3ScriptEncConverter.DistroPath(ConverterIdentifier); - if (!String.IsNullOrEmpty(distroPath)) - openFileDialogBrowse.InitialDirectory = Path.GetDirectoryName(distroPath); - else - openFileDialogBrowse.InitialDirectory = @"C:\"; - - if (openFileDialogBrowse.ShowDialog() == DialogResult.OK) - { - ResetFields(); - textBoxPython3Path.Text = openFileDialogBrowse.FileName; - } - } - - private void textBoxFileSpec_TextChanged(object sender, EventArgs e) + { + // since we use the same dialog for the python script and the python dll, don't keep the 'FileName' around, + // when searching for the latter + InitializeOpenFileDialog(openFileDialogBrowse.FileName, OpenFileDialogDefaultExtBrowseForDll, OpenFileDialogFilterBrowseForDll, OpenFileDialogTitleBrowseForDll); + + var distroPath = Py3ScriptEncConverter.DistroPath(ConverterIdentifier); + if (!String.IsNullOrEmpty(distroPath)) + openFileDialogBrowse.InitialDirectory = Path.GetDirectoryName(distroPath); + else + openFileDialogBrowse.InitialDirectory = @"C:\"; + + if (openFileDialogBrowse.ShowDialog() == DialogResult.OK) + { + ResetFields(); + textBoxPython3Path.Text = openFileDialogBrowse.FileName; + } + } + + private void InitializeOpenFileDialog(string fileName, string defaultExt, string filter, string title) + { + if (!string.IsNullOrEmpty(fileName) && fileName.Substring(fileName.Length - defaultExt.Length + 1).ToLower() != $".{defaultExt}") + fileName = ""; + openFileDialogBrowse.Title = title; + openFileDialogBrowse.DefaultExt = defaultExt; + openFileDialogBrowse.Filter = filter; + } + + private void textBox_TextChanged(object sender, EventArgs e) { if (m_bInitialized) // but only do this after we're already initialized { diff --git a/src/PyScriptEC/Py3ScriptEncConverter.cs b/src/PyScriptEC/Py3ScriptEncConverter.cs index 3f3cde55..30889a62 100644 --- a/src/PyScriptEC/Py3ScriptEncConverter.cs +++ b/src/PyScriptEC/Py3ScriptEncConverter.cs @@ -179,20 +179,34 @@ protected unsafe void Load() var strErrorExtraValue = strScriptPath; try { - var distroPath = DistroPath(ConverterIdentifier); - if (Runtime.PythonDLL != distroPath) - Runtime.PythonDLL = distroPath; - - if (!PythonEngine.IsInitialized) - { - PythonEngine.Initialize(); - } - - // causes access violation and may not be needed (since this isn't async): - // PythonEngine.BeginAllowThreads(); - dynamic sysModule = Py.Import("sys"); + var distroPath = DistroPath(ConverterIdentifier); + try + { + if (Runtime.PythonDLL != distroPath) + Runtime.PythonDLL = distroPath; + + if (!PythonEngine.IsInitialized) + { + PythonEngine.Initialize(); + } + } + catch (Exception e) + { + if (e.Message.Contains("This property must be set before runtime is initialized") && (Runtime.PythonDLL != distroPath)) + { + EncConverters.ThrowError(ErrStatus.CantOpenReadMap, $"You have to restart the {strDisplayName} Setup dialog to reset the Python interface"); + } + + // see if this helps (it doesn't seem to, but it also doesn't die... + PythonEngine.Shutdown(); + throw; + } + + // causes access violation and may not be needed (since this isn't async): + // PythonEngine.BeginAllowThreads(); + dynamic sysModule = Py.Import("sys"); strScriptDir = strScriptDir.Replace(@"\", "/"); - sysModule.path.append(strScriptDir); + sysModule.path.insert(0, strScriptDir); using (Py.GIL()) { From b70b44c76ac6506e016c3f41b3e27c5b2a764fe2 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Fri, 3 Nov 2023 05:31:25 -0500 Subject: [PATCH 061/113] tried some new parameter permutations on the PLinq query to run the multiple converters/translators in parallel until I found one that worked... Also, removed the data from 'mapOfRecentTranslations' for the current source text if the user presses F5, or it won't actually redo the processing --- .../BackTranslationHelperCtrl.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs index c542ba88..cd649df8 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs @@ -523,9 +523,9 @@ private async Task CallTranslators(BackTranslationHelperModel model) var thread = new Thread(() => { IEnumerable<(string TranslatedText, int Index)> results = Partitioner - .Create(translators, EnumerablePartitionerOptions.NoBuffering) + .Create(translators, EnumerablePartitionerOptions.None) .AsParallel() - .WithMergeOptions(ParallelMergeOptions.NotBuffered) + .WithMergeOptions(ParallelMergeOptions.FullyBuffered) .Select((theTranslatorPlusIndex) => { var theTranslator = theTranslatorPlusIndex.TheTranslator; @@ -540,14 +540,6 @@ private async Task CallTranslators(BackTranslationHelperModel model) }) .ToList(); - // This isn't really necessary, but for some reason, if we don't do it, then the thread returns immediately - // So if we get here, just reset the values we already set... - foreach (var result in results) - { - var index = result.Index; - model.TargetsPossible[index] = new TargetPossible { TargetData = result.TranslatedText, PossibleIndex = index, TranslatorName = TheTranslators[index].Name }; - } - waitForAllTranslatorsToFinish.Set(); }); thread.Start(); @@ -1080,6 +1072,13 @@ private void TextBoxTargetBackTranslation_PreviewKeyDown(object sender, PreviewK // to do. // _model.TargetData = null; // so it'll be reinitialized _model.TargetsPossible.Clear(); + + // also remove any existing translations for the current sourceData + var sourceToTranslate = _model.SourceToTranslate; + if (!string.IsNullOrEmpty(sourceToTranslate)) + { + _mapOfRecentTranslations.Values.ToList().ForEach(m => m.Remove(sourceToTranslate)); + } Reload(); return; } From e24526c4412f15aef28dd5b9958b23a4a35e9663 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Fri, 3 Nov 2023 06:09:34 -0500 Subject: [PATCH 062/113] The parallel processing seems to return before all of it is finished, resulting in the newTargetTexts having nulls in it. But due to the way we refresh when the dialog gets focus, it all works out in the end. (I think it has to do with how blocking can occur in the bowels of how the IEncConverter.Convert method is called, which forces the processing to return so it doesn't deadlock. Any thing I tried to force a more satisfying block does just deadlock... so this seem the least of all evils). If this turns out to be problematic for any reason, then we may just have to give up on running them in parallel until we redo the interface to support async calling...) --- src/BackTranslationHelper/BackTranslationHelperCtrl.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs index cd649df8..7a1e2502 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs @@ -391,10 +391,10 @@ public void SetNewTargetTexts(List newTargetTexts) { var textBoxesPossibleTargetTranslations = tableLayoutPanel.Controls.OfType().Where(l => l.Name.Contains("textBoxPossibleTargetTranslation")).ToList(); - // if the user clicks the progress bar to stop the translations, the number in newTargetTexts could be less - // than textBoxesPossibleTargetTranslations.Count - System.Diagnostics.Debug.Assert(newTargetTexts.Count <= textBoxesPossibleTargetTranslations.Count); - foreach (var targetText in newTargetTexts.Where(tt => tt != null)) + // The parallel processing seems to return before all of it is finished, resulting in the newTargetTexts having nulls in it. + var targetTexts = newTargetTexts.Where(tt => tt != null).ToList(); + System.Diagnostics.Debug.Assert(targetTexts.Count <= textBoxesPossibleTargetTranslations.Count); + foreach (var targetText in targetTexts) { if (targetText.PossibleIndex >= textBoxesPossibleTargetTranslations.Count) continue; @@ -505,7 +505,7 @@ private async Task CallTranslators(BackTranslationHelperModel model) // some of the possible target translators may have already been run by the client (e.g. Word always // does the 1st one). OR we may already have one or more and we're adding more... // So this is for any that haven't been done yet - var alreadyTranslatedTargetNames = model.TargetsPossible.Select(tp => tp.TranslatorName).ToList(); + var alreadyTranslatedTargetNames = model.TargetsPossible.Where(tt => tt != null).Select(tp => tp.TranslatorName).ToList(); var translators = TheTranslators.Where(t => !alreadyTranslatedTargetNames.Contains(t.Name)) .Select(t => new { TheTranslator = t, Index = TheTranslators.IndexOf(t) }) .ToList(); From d0a552617031017ab32d12cd3a6529bdc678e0d3 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Fri, 3 Nov 2023 06:11:46 -0500 Subject: [PATCH 063/113] add the ability to edit the encconverters from the ListForm for removing and reordering them. --- .../BackTranslationHelperCtrl.designer.cs | 6 +- .../TranslatorListForm.Designer.cs | 48 +++++++++----- .../TranslatorListForm.cs | 63 ++++++++++++++++++- 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs index d32d313e..19b5c7aa 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs @@ -118,10 +118,8 @@ private void InitializeComponent() // this.removeEncConverterToolStripMenuItem.Name = "removeEncConverterToolStripMenuItem"; this.removeEncConverterToolStripMenuItem.Size = new System.Drawing.Size(315, 22); - this.removeEncConverterToolStripMenuItem.Text = "Remove or Reorder &Translators/EncConverters"; - this.removeEncConverterToolStripMenuItem.ToolTipText = "Click to bring up a dialog to remove or reorder the Translators/EncConverters use" + - "d to generate one of the translated draft of the source text (e.g. Bing Translat" + - "or)"; + this.removeEncConverterToolStripMenuItem.Text = "Edit, Remove or Reorder &Translators/EncConverters"; + this.removeEncConverterToolStripMenuItem.ToolTipText = "Click to bring up a dialog to edit, remove or reorder the Translators/EncConverters."; this.removeEncConverterToolStripMenuItem.Click += new System.EventHandler(this.ChangeEncConverterToolStripMenuItem_Click); // // addEncConverterToolStripMenuItem diff --git a/src/BackTranslationHelper/TranslatorListForm.Designer.cs b/src/BackTranslationHelper/TranslatorListForm.Designer.cs index 8085f574..68c129ac 100644 --- a/src/BackTranslationHelper/TranslatorListForm.Designer.cs +++ b/src/BackTranslationHelper/TranslatorListForm.Designer.cs @@ -45,6 +45,7 @@ private void InitializeComponent() this.buttonMoveTranslatorDown = new System.Windows.Forms.Button(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.timerTooltip = new System.Windows.Forms.Timer(this.components); + this.buttonEditSelected = new System.Windows.Forms.Button(); this.tableLayoutPanel.SuspendLayout(); this.SuspendLayout(); // @@ -53,13 +54,13 @@ private void InitializeComponent() this.listBoxTranslatorNames.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.tableLayoutPanel.SetColumnSpan(this.listBoxTranslatorNames, 2); + this.tableLayoutPanel.SetColumnSpan(this.listBoxTranslatorNames, 3); this.helpProvider.SetHelpString(this.listBoxTranslatorNames, "This list displays all of the currently added Translator/EncConverters"); this.listBoxTranslatorNames.Location = new System.Drawing.Point(3, 26); this.listBoxTranslatorNames.Name = "listBoxTranslatorNames"; this.tableLayoutPanel.SetRowSpan(this.listBoxTranslatorNames, 2); this.helpProvider.SetShowHelp(this.listBoxTranslatorNames, true); - this.listBoxTranslatorNames.Size = new System.Drawing.Size(316, 212); + this.listBoxTranslatorNames.Size = new System.Drawing.Size(372, 303); this.listBoxTranslatorNames.TabIndex = 0; this.listBoxTranslatorNames.SelectedIndexChanged += new System.EventHandler(this.listBoxTranslatorNames_SelectedIndexChanged); this.listBoxTranslatorNames.MouseMove += new System.Windows.Forms.MouseEventHandler(this.listBoxTranslatorNames_MouseMove); @@ -68,10 +69,10 @@ private void InitializeComponent() // this.labelStatic.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.tableLayoutPanel.SetColumnSpan(this.labelStatic, 2); + this.tableLayoutPanel.SetColumnSpan(this.labelStatic, 3); this.labelStatic.Location = new System.Drawing.Point(3, 0); this.labelStatic.Name = "labelStatic"; - this.labelStatic.Size = new System.Drawing.Size(316, 23); + this.labelStatic.Size = new System.Drawing.Size(372, 23); this.labelStatic.TabIndex = 1; this.labelStatic.Text = "Choose the Translator/EncConverter to remove or reorder"; // @@ -80,7 +81,7 @@ private void InitializeComponent() this.buttonRemove.Anchor = System.Windows.Forms.AnchorStyles.Right; this.helpProvider.SetHelpString(this.buttonRemove, "Click this button to remove the selected translator/EncConverter from this projec" + "t"); - this.buttonRemove.Location = new System.Drawing.Point(83, 256); + this.buttonRemove.Location = new System.Drawing.Point(151, 346); this.buttonRemove.Name = "buttonRemove"; this.helpProvider.SetShowHelp(this.buttonRemove, true); this.buttonRemove.Size = new System.Drawing.Size(75, 23); @@ -93,7 +94,7 @@ private void InitializeComponent() this.buttonCancel.Anchor = System.Windows.Forms.AnchorStyles.Left; this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); - this.buttonCancel.Location = new System.Drawing.Point(164, 256); + this.buttonCancel.Location = new System.Drawing.Point(232, 346); this.buttonCancel.Name = "buttonCancel"; this.helpProvider.SetShowHelp(this.buttonCancel, true); this.buttonCancel.Size = new System.Drawing.Size(75, 23); @@ -106,16 +107,18 @@ private void InitializeComponent() this.tableLayoutPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.tableLayoutPanel.ColumnCount = 3; - this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel.ColumnCount = 4; this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.00001F)); + this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel.Controls.Add(this.labelStatic, 0, 0); - this.tableLayoutPanel.Controls.Add(this.buttonCancel, 1, 3); + this.tableLayoutPanel.Controls.Add(this.buttonCancel, 2, 3); this.tableLayoutPanel.Controls.Add(this.listBoxTranslatorNames, 0, 1); - this.tableLayoutPanel.Controls.Add(this.buttonRemove, 0, 3); - this.tableLayoutPanel.Controls.Add(this.buttonMoveTranslatorUp, 2, 1); - this.tableLayoutPanel.Controls.Add(this.buttonMoveTranslatorDown, 2, 2); + this.tableLayoutPanel.Controls.Add(this.buttonMoveTranslatorUp, 3, 1); + this.tableLayoutPanel.Controls.Add(this.buttonMoveTranslatorDown, 3, 2); + this.tableLayoutPanel.Controls.Add(this.buttonRemove, 1, 3); + this.tableLayoutPanel.Controls.Add(this.buttonEditSelected, 0, 3); this.tableLayoutPanel.Location = new System.Drawing.Point(12, 12); this.tableLayoutPanel.Name = "tableLayoutPanel"; this.tableLayoutPanel.RowCount = 4; @@ -123,14 +126,14 @@ private void InitializeComponent() this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel.Size = new System.Drawing.Size(351, 283); + this.tableLayoutPanel.Size = new System.Drawing.Size(408, 372); this.tableLayoutPanel.TabIndex = 4; // // buttonMoveTranslatorUp // this.buttonMoveTranslatorUp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.buttonMoveTranslatorUp.Image = global::BackTranslationHelper.Properties.Resources.FillUpHS; - this.buttonMoveTranslatorUp.Location = new System.Drawing.Point(325, 112); + this.buttonMoveTranslatorUp.Location = new System.Drawing.Point(381, 157); this.buttonMoveTranslatorUp.Name = "buttonMoveTranslatorUp"; this.buttonMoveTranslatorUp.Size = new System.Drawing.Size(23, 23); this.buttonMoveTranslatorUp.TabIndex = 9; @@ -141,7 +144,7 @@ private void InitializeComponent() // buttonMoveTranslatorDown // this.buttonMoveTranslatorDown.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; - this.buttonMoveTranslatorDown.Location = new System.Drawing.Point(325, 141); + this.buttonMoveTranslatorDown.Location = new System.Drawing.Point(381, 186); this.buttonMoveTranslatorDown.Name = "buttonMoveTranslatorDown"; this.buttonMoveTranslatorDown.Size = new System.Drawing.Size(23, 23); this.buttonMoveTranslatorDown.TabIndex = 9; @@ -154,12 +157,23 @@ private void InitializeComponent() this.timerTooltip.Interval = 500; this.timerTooltip.Tick += new System.EventHandler(this.timerTooltip_Tick); // + // buttonEditSelected + // + this.buttonEditSelected.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.buttonEditSelected.Location = new System.Drawing.Point(70, 346); + this.buttonEditSelected.Name = "buttonEditSelected"; + this.buttonEditSelected.Size = new System.Drawing.Size(75, 23); + this.buttonEditSelected.TabIndex = 2; + this.buttonEditSelected.Text = "&Edit"; + this.toolTip.SetToolTip(this.buttonEditSelected, "Click to edit the selected Translator/EncConverter"); + this.buttonEditSelected.Click += new System.EventHandler(this.buttonEditSelected_Click); + // // TranslatorListForm // this.AcceptButton = this.buttonRemove; this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.CancelButton = this.buttonCancel; - this.ClientSize = new System.Drawing.Size(375, 307); + this.ClientSize = new System.Drawing.Size(432, 396); this.Controls.Add(this.tableLayoutPanel); this.HelpButton = true; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); @@ -170,6 +184,7 @@ private void InitializeComponent() this.Text = "Reorder/Remove Translator"; this.tableLayoutPanel.ResumeLayout(false); this.ResumeLayout(false); + } private ListBox listBoxTranslatorNames; @@ -184,5 +199,6 @@ private void InitializeComponent() private Button buttonMoveTranslatorDown; #endregion + private Button buttonEditSelected; } } diff --git a/src/BackTranslationHelper/TranslatorListForm.cs b/src/BackTranslationHelper/TranslatorListForm.cs index 7cec0100..c64f05c1 100644 --- a/src/BackTranslationHelper/TranslatorListForm.cs +++ b/src/BackTranslationHelper/TranslatorListForm.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using ECInterfaces; using System.Linq; +using SilEncConverters40; +using System.Reflection; namespace BackTranslationHelper { @@ -29,8 +31,9 @@ public TranslatorListForm(List translators) m_mapLbItems2Tooltips[translator.Name] = translator.ToString(); } - // disable the add button (until an implementation type is selected) - buttonRemove.Enabled = false; + // disable the buttons (until an implementation type is selected) + buttonRemove.Enabled = buttonEditSelected.Enabled = + buttonMoveTranslatorDown.Enabled = buttonMoveTranslatorUp.Enabled = false; labelStatic.Text = $"Choose the Translator/EncConverter to remove"; } @@ -55,7 +58,7 @@ private void buttonRemove_Click(object sender, System.EventArgs e) private void listBoxTranslatorNames_SelectedIndexChanged(object sender, EventArgs e) { - this.buttonRemove.Enabled = buttonMoveTranslatorDown.Enabled = buttonMoveTranslatorUp.Enabled = (this.listBoxTranslatorNames.SelectedItem != null); + this.buttonRemove.Enabled = buttonEditSelected.Enabled = buttonMoveTranslatorDown.Enabled = buttonMoveTranslatorUp.Enabled = (this.listBoxTranslatorNames.SelectedItem != null); } private void buttonCancel_Click(object sender, System.EventArgs e) @@ -127,5 +130,59 @@ private void buttonMoveTranslatorDown_Click(object sender, EventArgs e) buttonRemove.Text = OkButtonTextSave; } + + private void buttonEditSelected_Click(object sender, EventArgs e) + { + if (listBoxTranslatorNames.SelectedIndex == -1) + return; + + // check for this item in the repository collection (should exist, but sometimes, doesn't!) + var index = listBoxTranslatorNames.SelectedIndex; + var converterName = listBoxTranslatorNames.SelectedItem as String; + if (!DirectableEncConverter.EncConverters.ContainsKey(converterName)) + return; + + var theEC = DirectableEncConverter.EncConverters[converterName]; + Debug.Assert(theEC != null); + + // get the name (but if it's a temporary name, then just start from scratch (with no name) + string strFriendlyName = theEC.Name; + if (strFriendlyName.IndexOf(EncConverters.cstrTempConverterPrefix) == 0) + strFriendlyName = null; + + bool bTooltipActive = toolTip.Active; + toolTip.Active = false; + if (DirectableEncConverter.EncConverters.AutoConfigureEx(theEC, theEC.ConversionType, ref strFriendlyName, theEC.LeftEncodingID, theEC.RightEncodingID)) + { + // since even the name could theoretically change, remove the existing one and ... + if (m_mapLbItems2Tooltips.ContainsKey(converterName)) + m_mapLbItems2Tooltips.Remove(converterName); + + // remove the old one from the listbox also + if (this.listBoxTranslatorNames.Items.Contains(converterName)) + this.listBoxTranslatorNames.Items.Remove(converterName); + + // get a possible new name + Debug.Assert(!String.IsNullOrEmpty(strFriendlyName)); + converterName = strFriendlyName; + + this.listBoxTranslatorNames.Items.Insert(index, converterName); + this.listBoxTranslatorNames.SelectedIndex = index; + + // make it visible + this.listBoxTranslatorNames.TopIndex = index; + + // also update the tooltip and fixup the button state + // (but first re-get the converter since (for some types, e.g. CmpdEncConverter) + // it might be totally different. + theEC = DirectableEncConverter.EncConverters[converterName]; + if (theEC != null) + m_mapLbItems2Tooltips[converterName] = theEC.ToString(); + + // finally, make this a Save situation: + buttonRemove.Text = OkButtonTextSave; + } + toolTip.Active = bTooltipActive; + } } } From af48353db3289131df6f578d1db100c30ab4af1a Mon Sep 17 00:00:00 2001 From: bobeaton Date: Fri, 3 Nov 2023 06:27:59 -0500 Subject: [PATCH 064/113] removed set-output and updated msbuild to get rid of Annotations warnings --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4590a81f..13d37be6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@v3 - name: Add MSBuild to PATH - uses: microsoft/setup-msbuild@v1.0.2 + uses: microsoft/setup-msbuild@v1.3.1 - name: Fetch nuget dependecies run: nuget restore "${{env.SOLUTION_FILE_PATH}}" From 1cf4b73a36476648a30d417e82812598deafd50b Mon Sep 17 00:00:00 2001 From: bobeaton Date: Fri, 3 Nov 2023 11:38:59 -0500 Subject: [PATCH 065/113] fix the sizing of the boxes on the BTHelper ctrl so they're all even --- .../BackTranslationHelperCtrl.cs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs index 7a1e2502..e67bd452 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs @@ -127,16 +127,23 @@ public void Initialize(BackTranslationHelperModel model) var projectName = BackTranslationHelperDataSource.ProjectName; toolStripTextBoxStatus.Size = CalculateStatusLineSize(toolStripTextBoxStatus, settingsToolStripMenuItem); + var showSourceText = !Properties.Settings.Default.HideSourceText; + var showCurrentTargetText = !Properties.Settings.Default.HideCurrentTargetText; + var numOfTranslators = TheTranslators.Count; + var totalTextBoxes = (showSourceText ? 1 : 0) + // the total number of visible text boxes + (showCurrentTargetText ? 1 : 0) + + numOfTranslators + 1; + float percentageHeight = 100 / totalTextBoxes; + var nRowStyleOffset = 0; // start w/ the Source Language text box - ExpandOrCollapse(!Properties.Settings.Default.HideSourceText, nRowStyleOffset++, + ExpandOrCollapse(showSourceText, nRowStyleOffset++, percentageHeight, textBoxSourceData, GetSourceLanguageFontForProject(projectName), GetSourceLanguageRightToLeftForProject(projectName)); var targetLanguageFont = GetTargetLanguageFontForProject(projectName); var targetLanguageRightToLeft = GetTargetLanguageRightToLeftForProject(projectName); - var hideCurrentTargetText = Properties.Settings.Default.HideCurrentTargetText; - ExpandOrCollapse(displayExistingTargetTranslation && !hideCurrentTargetText, nRowStyleOffset++, + ExpandOrCollapse(displayExistingTargetTranslation && showCurrentTargetText, nRowStyleOffset++, percentageHeight, textBoxTargetTextExisting, targetLanguageFont, targetLanguageRightToLeft); textBoxTargetBackTranslation.Font = targetLanguageFont; @@ -148,7 +155,6 @@ public void Initialize(BackTranslationHelperModel model) var labelsPossibleTargetTranslations = tableLayoutPanel.Controls.OfType

+

Target

+ + +
+
+ +

API instructions

+
    +
  • GET /api/v1/translate/languages/
  • +
  • POST /api/v1/translate/ with sourceLanguage, targetLanguage, text
  • +
+ + + diff --git a/src/EcTranslators/NllbTranslator/NllbTranslator.cs b/src/EcTranslators/NllbTranslator/NllbTranslator.cs index 71789816..77e49a9e 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslator.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslator.cs @@ -14,7 +14,7 @@ namespace Nllb { - public interface ITranslator : IDisposable + public interface ITranslator : IDisposable { /// Translate specified text from source language into target language. /// Text to translate; must not be empty. @@ -81,7 +81,7 @@ public Translator(string authKey, DeepL.TranslatorOptions? options = null) if (!headers.ContainsKey("Authorization")) { - headers.Add("Authorization", $"SIL-NLLB-Auth-Key {authKey}"); + headers.Add("Authorization", authKey); } var clientFactory = options.ClientFactory ?? (() => diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs index 23965706..5c9f5088 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs @@ -10,6 +10,9 @@ using SilEncConverters40.EcTranslators.NllbTranslator; using System.Net; using Newtonsoft.Json; +using System.IO; +using System.Text; +using static System.Environment; namespace SilEncConverters40.EcTranslators.NllbTranslator { @@ -18,8 +21,6 @@ public partial class NllbTranslatorAutoConfigDialog : AutoConfigDialog private readonly ComboBoxItem SourceLanguageNameMustBeConfigured = new ComboBoxItem { Display = "Select Source Language" }; private readonly ComboBoxItem TargetLanguageNameMustBeConfigured = new ComboBoxItem { Display = "Select Target Language" }; - // protected List LanguagesSupported; - public NllbTranslatorAutoConfigDialog ( IEncConverters aECs, @@ -53,17 +54,19 @@ bool bIsInRepository ); Util.DebugWriteLine(this, "called base.Initalize"); - var languagesSupported = GetLanguagesSupportedAndInitializeComboBoxes(); - if (languagesSupported == null) - return; - - // if we're editing converter, then set the Converter Spec and say it's unmodified - if (m_bEditMode) + // if we're editing converter, then set the Converter Spec and say it's unmodified + if (m_bEditMode) { System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(ConverterIdentifier)); - ParseConverterIdentifier(ConverterIdentifier, out string fromLanguage, out string toLanguage); + ParseConverterIdentifier(ConverterIdentifier, out string pathToDockerProject, out string fromLanguage, out string toLanguage, + out string apiKey, out string endpoint); + var languagesSupported = GetLanguagesSupportedAndInitializeComboBoxes(true, apiKey, endpoint); + if (languagesSupported == null) + return; + + DockerProjectFolderPath = pathToDockerProject; var selectedItem = comboBoxSourceLanguages.Items.Cast().FirstOrDefault(l => l.Code == fromLanguage); comboBoxSourceLanguages.SelectedItem = selectedItem; comboBoxTargetLanguages.SelectedItem = languagesSupported.FirstOrDefault(l => l.Code == toLanguage); @@ -71,6 +74,16 @@ bool bIsInRepository } else { + // if we've done one before... see if it still works + DockerProjectFolderPath = Properties.Settings.Default.NllbTranslatorPathToDockerProject; + + var apiKey = NllbTranslatorApiKey; + var endpoint = NllbTranslatorEndpoint; + if (!String.IsNullOrEmpty(apiKey) && !String.IsNullOrEmpty(endpoint)) + GetLanguagesSupportedAndInitializeComboBoxes(false, apiKey, endpoint); + else + buttonConfigureNllbModel.Enabled = false; // until the path is chosen + comboBoxSourceLanguages.SelectedItem = SourceLanguageNameMustBeConfigured; comboBoxTargetLanguages.SelectedItem = TargetLanguageNameMustBeConfigured; } @@ -79,25 +92,33 @@ bool bIsInRepository helpProvider.SetHelpString(comboBoxSourceLanguages, Properties.Resources.HelpForNllbTranslatorSourceLanguagesComboBox); helpProvider.SetHelpString(comboBoxTargetLanguages, Properties.Resources.HelpForNllbTranslatorTargetLanguagesComboBox); - helpProvider.SetHelpString(buttonSetNllbTranslateApiKey, Properties.Resources.HelpForNllbTranslatorAddYourOwnApiKey); + helpProvider.SetHelpString(buttonConfigureNllbModel, Properties.Resources.HelpForNllbTranslatorAddYourOwnApiKey); Util.DebugWriteLine(this, "END"); } - private List GetLanguagesSupportedAndInitializeComboBoxes() - { - var langMap = GetCapabilities().GetAwaiter().GetResult(); - if (langMap == null) - return null; - - var languagesSupported = langMap.Select(kvp => new ComboBoxItem { Code = kvp.Key, Display = kvp.Value }) - .OrderBy(c => c.Display) - .ToList(); - InitializeSourceAndTargetLanguages(languagesSupported); - return languagesSupported; - } + private List GetLanguagesSupportedAndInitializeComboBoxes(bool showError, string apiKey, string endpoint) + { + // for our purposes here, we only need the Model configuration (so we can hit the endpoint for languages supported); + // not the specific languages we want to convert To/From. So we don't want to use 'OnApply' here, bkz it will fails + // so just create a temporary one and set the key/endpoint and use it to get the languages supported. + var theNllbEncConverter = new NllbTranslatorEncConverter + { + ApiKey = apiKey, + Endpoint = endpoint + }; + var langMap = theNllbEncConverter.GetCapabilities(showError).GetAwaiter().GetResult(); + if (langMap == null) + return null; + + var languagesSupported = langMap.Select(kvp => new ComboBoxItem { Code = kvp.Key, Display = kvp.Value }) + .OrderBy(c => c.Display) + .ToList(); + InitializeSourceAndTargetLanguages(languagesSupported); + return languagesSupported; + } - public NllbTranslatorAutoConfigDialog + public NllbTranslatorAutoConfigDialog ( IEncConverters aECs, string strFriendlyName, @@ -125,6 +146,13 @@ string strTestData // to make sure that the user has correctly configured a legitimate converter. protected override bool OnApply() { + var dockerProjectFolder = DockerProjectFolderPath; + if (String.IsNullOrEmpty(dockerProjectFolder)) + { + MessageBox.Show(this, "The Path to the Docker Project Folder must be entered!", EncConverters.cstrCaption); + return false; + } + var selectedToLanguage = (ComboBoxItem)comboBoxTargetLanguages.SelectedItem; if ((selectedToLanguage == null) || (TargetLanguageNameMustBeConfigured == selectedToLanguage)) { @@ -140,9 +168,16 @@ protected override bool OnApply() } // for this converter, use the source and target language codes (e.g. hin_Deva) as the converter identifier - ConverterIdentifier = String.Format("{0};{1}", + // UPDATE: also include the path to the project and the API key (encrypted) and the Endpoint, since it's + // possible to have multiple models running. The latter two can be blank, though to just revert to the + // defaults (i.e. your-api-key-here and http://localhost:8000, respectively) + // P.S. no need to validate them, bkz if they don't exist, then we wouldn't have the selectedLgs either + ConverterIdentifier = String.Format("{0};{1};{2};{3};{4}", + dockerProjectFolder, selectedFromLanguage.Code, - selectedToLanguage.Code); + selectedToLanguage.Code, + NllbTranslatorEndpoint, + EncryptionClass.Encrypt(NllbTranslatorApiKey)); return base.OnApply(); } @@ -219,19 +254,46 @@ public override int GetHashCode() private void ButtonSetNllbTranslateApiKey_Click(object sender, EventArgs e) { - using var dlg = new QueryForEndpointAndApiKey(NllbTranslatorApiKey, NllbTranslatorEndpoint); + var dockerProjectFolderPath = DockerProjectFolderPath; + if (string.IsNullOrEmpty(dockerProjectFolderPath)) + { + MessageBox.Show($"You must browse for/enter the path to where the Docker Project is located or should be created.", EncConverters.cstrCaption); + return; + } + + using var dlg = new QueryForEndpointAndApiKey(dockerProjectFolderPath, NllbTranslatorApiKey, NllbTranslatorEndpoint); if (dlg.ShowDialog() == DialogResult.OK) { - NllbTranslatorApiKey = dlg.TranslatorKey; + // if the user configures a model, then save the API Key and Endpoint for any new converters they create + // the path was set earlier, but save it here (since this means the user at least intended to do something, + // whether they build the model (successfully) or not) + Properties.Settings.Default.NllbTranslatorPathToDockerProject = dockerProjectFolderPath; + NllbTranslatorApiKey = dlg.TranslatorApiKey; var endpoint = dlg.Endpoint; NllbTranslatorEndpoint = (endpoint == Properties.Settings.Default.NllbTranslatorEndpoint) ? null : endpoint; Properties.Settings.Default.Save(); - _nllbTranslator = null; // so it recreates the client with the new settings + m_aEC = null; // reset the associated EncConverter instance so it'll get rebuilt w/ the new parameters + + // in case something changed, reinitialize the combo boxes + GetLanguagesSupportedAndInitializeComboBoxes(m_bInitialized, dlg.TranslatorApiKey, dlg.Endpoint); + } + } - // in case something changed, reinitialize - GetLanguagesSupportedAndInitializeComboBoxes(); - } + private string DockerProjectFolderPath + { + get { return textBoxDockerProjectFolder.Text?.Trim(); } + set { textBoxDockerProjectFolder.Text = value; } + } + + private void buttonBrowse_Click(object sender, System.EventArgs e) + { + folderBrowserDialog.SelectedPath = Path.Combine(Path.Combine(Environment.GetFolderPath(SpecialFolder.CommonApplicationData), "SIL"), "NLLB Docker Folder" + Path.PathSeparator); + if (folderBrowserDialog.ShowDialog() == DialogResult.OK) + { + DockerProjectFolderPath = folderBrowserDialog.SelectedPath; + buttonConfigureNllbModel.Enabled = true; + } } private void ComboBoxSourceLanguages_SelectedIndexChanged_1(object sender, EventArgs e) diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.designer.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.designer.cs index 6f2e4409..4a8bf9f2 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.designer.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.designer.cs @@ -31,13 +31,17 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.openFileDialogBrowse = new System.Windows.Forms.OpenFileDialog(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelFolderPath = new System.Windows.Forms.Label(); + this.textBoxDockerProjectFolder = new System.Windows.Forms.TextBox(); + this.buttonBrowse = new System.Windows.Forms.Button(); + this.buttonConfigureNllbModel = new System.Windows.Forms.Button(); this.labelSourceLanguage = new System.Windows.Forms.Label(); - this.labelTargetLanguage = new System.Windows.Forms.Label(); this.comboBoxSourceLanguages = new System.Windows.Forms.ComboBox(); + this.labelTargetLanguage = new System.Windows.Forms.Label(); this.comboBoxTargetLanguages = new System.Windows.Forms.ComboBox(); - this.buttonSetNllbTranslateApiKey = new System.Windows.Forms.Button(); + this.labelModelConfiguration = new System.Windows.Forms.Label(); + this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog(); this.tabControl.SuspendLayout(); this.tabPageSetup.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); @@ -67,87 +71,126 @@ private void InitializeComponent() this.helpProvider.SetHelpString(this.buttonSaveInRepository, "\r\nClick to add this converter to the system repository permanently.\r\n "); this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); // - // openFileDialogBrowse - // - this.openFileDialogBrowse.DefaultExt = "tec"; - this.openFileDialogBrowse.Filter = "TECkit (compiled) files (*.tec)|*.tec|TECkit (compilable) files (*.map)|*.map"; - this.openFileDialogBrowse.Title = "Browse for TECkit map"; - // // tableLayoutPanel1 // this.tableLayoutPanel1.ColumnCount = 3; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel1.Controls.Add(this.labelSourceLanguage, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.labelTargetLanguage, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.comboBoxSourceLanguages, 1, 0); - this.tableLayoutPanel1.Controls.Add(this.comboBoxTargetLanguages, 1, 1); - this.tableLayoutPanel1.Controls.Add(this.buttonSetNllbTranslateApiKey, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.labelFolderPath, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxDockerProjectFolder, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.buttonBrowse, 2, 0); + this.tableLayoutPanel1.Controls.Add(this.buttonConfigureNllbModel, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.labelSourceLanguage, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.comboBoxSourceLanguages, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.labelTargetLanguage, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.comboBoxTargetLanguages, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.labelModelConfiguration, 1, 4); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowCount = 5; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); this.tableLayoutPanel1.TabIndex = 2; // + // labelFolderPath + // + this.labelFolderPath.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelFolderPath.AutoSize = true; + this.labelFolderPath.Location = new System.Drawing.Point(3, 18); + this.labelFolderPath.Name = "labelFolderPath"; + this.labelFolderPath.Size = new System.Drawing.Size(113, 13); + this.labelFolderPath.TabIndex = 1; + this.labelFolderPath.Text = "Docker Project Folder:"; + // + // textBoxDockerProjectFolder + // + this.textBoxDockerProjectFolder.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxDockerProjectFolder.Location = new System.Drawing.Point(122, 15); + this.textBoxDockerProjectFolder.Name = "textBoxDockerProjectFolder"; + this.textBoxDockerProjectFolder.Size = new System.Drawing.Size(439, 20); + this.textBoxDockerProjectFolder.TabIndex = 2; + // + // buttonBrowse + // + this.buttonBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.buttonBrowse.Location = new System.Drawing.Point(567, 13); + this.buttonBrowse.Name = "buttonBrowse"; + this.buttonBrowse.Size = new System.Drawing.Size(26, 23); + this.buttonBrowse.TabIndex = 3; + this.buttonBrowse.Text = "..."; + this.buttonBrowse.Click += new System.EventHandler(this.buttonBrowse_Click); + // + // buttonConfigureNllbModel + // + this.buttonConfigureNllbModel.Location = new System.Drawing.Point(122, 53); + this.buttonConfigureNllbModel.Name = "buttonConfigureNllbModel"; + this.buttonConfigureNllbModel.Size = new System.Drawing.Size(224, 23); + this.buttonConfigureNllbModel.TabIndex = 3; + this.buttonConfigureNllbModel.Text = "Configure NLLB Model"; + this.buttonConfigureNllbModel.UseVisualStyleBackColor = true; + this.buttonConfigureNllbModel.Click += new System.EventHandler(this.ButtonSetNllbTranslateApiKey_Click); + // // labelSourceLanguage // this.labelSourceLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; this.labelSourceLanguage.AutoSize = true; - this.labelSourceLanguage.Location = new System.Drawing.Point(3, 18); + this.labelSourceLanguage.Location = new System.Drawing.Point(25, 118); this.labelSourceLanguage.Name = "labelSourceLanguage"; this.labelSourceLanguage.Size = new System.Drawing.Size(91, 13); - this.labelSourceLanguage.TabIndex = 6; + this.labelSourceLanguage.TabIndex = 4; this.labelSourceLanguage.Text = "Source language:"; // - // labelTargetLanguage - // - this.labelTargetLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.labelTargetLanguage.AutoSize = true; - this.labelTargetLanguage.Location = new System.Drawing.Point(6, 68); - this.labelTargetLanguage.Name = "labelTargetLanguage"; - this.labelTargetLanguage.Size = new System.Drawing.Size(88, 13); - this.labelTargetLanguage.TabIndex = 8; - this.labelTargetLanguage.Text = "Target language:"; - // // comboBoxSourceLanguages // this.comboBoxSourceLanguages.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.comboBoxSourceLanguages.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBoxSourceLanguages.FormattingEnabled = true; - this.comboBoxSourceLanguages.Location = new System.Drawing.Point(100, 14); + this.comboBoxSourceLanguages.Location = new System.Drawing.Point(122, 114); this.comboBoxSourceLanguages.Name = "comboBoxSourceLanguages"; - this.comboBoxSourceLanguages.Size = new System.Drawing.Size(493, 21); - this.comboBoxSourceLanguages.TabIndex = 7; + this.comboBoxSourceLanguages.Size = new System.Drawing.Size(439, 21); + this.comboBoxSourceLanguages.TabIndex = 5; this.comboBoxSourceLanguages.SelectedIndexChanged += new System.EventHandler(this.ComboBoxSourceLanguages_SelectedIndexChanged_1); // + // labelTargetLanguage + // + this.labelTargetLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelTargetLanguage.AutoSize = true; + this.labelTargetLanguage.Location = new System.Drawing.Point(28, 168); + this.labelTargetLanguage.Name = "labelTargetLanguage"; + this.labelTargetLanguage.Size = new System.Drawing.Size(88, 13); + this.labelTargetLanguage.TabIndex = 6; + this.labelTargetLanguage.Text = "Target language:"; + // // comboBoxTargetLanguages // this.comboBoxTargetLanguages.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.comboBoxTargetLanguages.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBoxTargetLanguages.FormattingEnabled = true; - this.comboBoxTargetLanguages.Location = new System.Drawing.Point(100, 64); + this.comboBoxTargetLanguages.Location = new System.Drawing.Point(122, 164); this.comboBoxTargetLanguages.Name = "comboBoxTargetLanguages"; - this.comboBoxTargetLanguages.Size = new System.Drawing.Size(493, 21); - this.comboBoxTargetLanguages.TabIndex = 9; + this.comboBoxTargetLanguages.Size = new System.Drawing.Size(439, 21); + this.comboBoxTargetLanguages.TabIndex = 7; this.comboBoxTargetLanguages.SelectedIndexChanged += new System.EventHandler(this.ComboBoxTargetLanguages_SelectedIndexChanged_1); // - // buttonSetNllbTranslateApiKey + // labelModelConfiguration + // + this.labelModelConfiguration.AutoSize = true; + this.labelModelConfiguration.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelModelConfiguration.Location = new System.Drawing.Point(122, 200); + this.labelModelConfiguration.Name = "labelModelConfiguration"; + this.labelModelConfiguration.Size = new System.Drawing.Size(439, 194); + this.labelModelConfiguration.TabIndex = 8; + // + // folderBrowserDialog // - this.buttonSetNllbTranslateApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.buttonSetNllbTranslateApiKey.Location = new System.Drawing.Point(100, 368); - this.buttonSetNllbTranslateApiKey.Name = "buttonSetNllbTranslateApiKey"; - this.buttonSetNllbTranslateApiKey.Size = new System.Drawing.Size(294, 23); - this.buttonSetNllbTranslateApiKey.TabIndex = 14; - this.buttonSetNllbTranslateApiKey.Text = "Enter the Api Key and Endpoint"; - this.buttonSetNllbTranslateApiKey.UseVisualStyleBackColor = true; - this.buttonSetNllbTranslateApiKey.Click += new System.EventHandler(this.ButtonSetNllbTranslateApiKey_Click); + this.folderBrowserDialog.Description = "Browse and create a folder into which we will write the Docker Project files"; + this.folderBrowserDialog.RootFolder = System.Environment.SpecialFolder.MyComputer; // // NllbTranslatorAutoConfigDialog // @@ -167,12 +210,16 @@ private void InitializeComponent() } #endregion - private System.Windows.Forms.OpenFileDialog openFileDialogBrowse; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; private System.Windows.Forms.Label labelSourceLanguage; private System.Windows.Forms.Label labelTargetLanguage; private System.Windows.Forms.ComboBox comboBoxSourceLanguages; private System.Windows.Forms.ComboBox comboBoxTargetLanguages; - private System.Windows.Forms.Button buttonSetNllbTranslateApiKey; + private System.Windows.Forms.Button buttonConfigureNllbModel; + private System.Windows.Forms.Label labelModelConfiguration; + private System.Windows.Forms.Label labelFolderPath; + private System.Windows.Forms.TextBox textBoxDockerProjectFolder; + private System.Windows.Forms.Button buttonBrowse; + private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog; } } diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.resx b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.resx index f1434d65..74caa030 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.resx +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.resx @@ -1,4 +1,4 @@ - + @@ -47,6 +47,8 @@ href="NLLB_Translate_Plug-in_About_box_files/colorschememapping.xml"> A screenshot of a computer

Description automatically generated

+v:shapes="_x0000_i1038">

Figure Update Powershell winget

+float:none;word-spacing:0px'> winget

If this doesn’t work, then you can install the latest version of Powershell by following the instructions on Install Docker< have the latter installed), as shown here:

+src="NLLB_Translate_Plug-in_About_box_files/image004.jpg" v:shapes="_x0000_i1037">

Figure 2: Docker Installer

-

After the installation is complete, you will need to -restart your computer. Then open Docker for -Desktop and accept the agreement to complete the installation using the -recommended settings (requires administrator password).

+

After the installation is complete, restart your computer. +Then open Docker for Desktop and accept +the agreement to complete the installation using the recommended settings +(requires administrator password).

-

Once this is complete, you can either sign up or sign in or you can just Continue -without signing in.

+

Once this is complete, it will ask you to either sign up +or sign in or you can just Continue without signing in.

Once this is complete, you can bring up the NLLB Translator Setup dialog to complete the configuration.

-

Setup Tab

+

Setup +Tab

To bring up the Setup dialog for the NLLB Translator, you can run, for example, the Clipboard EncConverter installed as part of SILConverters. Then right-click on its small -icon in the system tray and choose the Edit or -Delete Converters menu item:

+class=MsoSubtleEmphasis>SILConverters. Then right-click on its small icon in the system tray +and choose the Edit or Delete Converters +menu item:

+src="NLLB_Translate_Plug-in_About_box_files/image012.jpg" v:shapes="_x0000_i1035">

Figure 4: Select and Add New Converter type

+yes'>4: Select and Add New Converter type

 

-

This will bring up the Setup dialog for the NLLB Translator -EncConverter:

+

This will bring up the Setup dialog for the NLLB +Translator EncConverter:

+src="NLLB_Translate_Plug-in_About_box_files/image001.jpg" v:shapes="Picture_x0020_5">

Figure : Folder Browse Dialog

+

 

+

2)      Click on this button to bring up a dialog where you will -make several choices to configure which NLLB model, etc., you want to use (see -below).

+style='color:black'>Click on this button to bring up the NLLB Model Configuration +dialog where you will make several choices to configure which NLLB model, etc., +you want to use (see below).

Setup Tab style='mso-bookmark:_Ref133733171'>4)      This -combo box is for selecting the Target language the input text should be -translated into.

+combo box is for selecting the Target language to translate into.

< above in the Setup dialog) to bring up the NLLB Model Configuration dialog:

+src="NLLB_Translate_Plug-in_About_box_files/image006.jpg" v:shapes="Picture_x0020_7">

Figure : Model Configuration Dialog

+

 

+

The numbers in the above image correspond to these settings:

+tab-stops:.5in'>The numbers in the above image correspond to these settings:

1)< style='color:black'>This edit box is to enter an API Key which would then be required to access the NLLB Model for translation. If you only plan to use your model from your personal computer or from another computer on your local -network, you can just keep the default value. But if you plan to host and access -the model from the internet, then this allows you to specify a custom API key to -restrict access.

+network, you can just keep the default value or remove the key altogether. But +if you plan to host and access the model from the internet, then this allows +you to specify a custom API key to restrict access.

3)      This edit box is to enter the endpoint through which the -model can be accessed. If you only plan to use your model from your personal -computer, you can just keep the default value. If you plan to access it from -another computer on your local network, you could enter the IP address of the -computer that is hosting the model (e.g. http://192.168.62.154:8000). Note that if you plan to share your model with other -computers, you may need to make a change to the firewall on the computer that -is hosting the model to allow access to port 8000 (see e.g. http://192.168.62.154:8000).

+ +

Note that if you plan to share your +model with other computers, you may need to make a change to the firewall on +the computer that is hosting the model to allow access to port 8000 (see this page for hints on how to do this).

It’s also possible to use a -different port to access the model (i.e. in place of the value 8000 above). If -you try to host multiple NLLB models, you will have to use a different port if -you want to access them via different EncConverters. You can make the port be -whatever you want, but again, you might need to adjust the firewall to allow -inbound traffic for whatever port you choose.

+different port to access the model (i.e. in place of the +value 8000 above). If you plan to host multiple NLLB models at the same time, +you will have to use a different port for each one to access them simultaneously. +The port number can be whatever you want, but again, you might need to adjust +the firewall to allow inbound traffic for whatever port you choose.

4)< once you’ve chosen the parameters you want, click the Create Docker Project button to continue. The Setup dialog will then install the necessary files, configured with the -settings you choose, into the folder you entered on the Setup Dialog. After -this it will display this msg to ask you to build the Docker container:

+settings you choose, into the folder you entered on the Setup Dialog (see (1) +in the Setup Tab +section above).

+ +

After the files are created, you will see this msg indicating the +next step is to build the Docker container (you can leave this box up while you +do the next steps):

A screenshot of a computer program

Description automatically generated

+v:shapes="_x0000_i1030">

Figure 8: Powershell after NLLB Model is built and running

+yes'>8: Powershell after NLLB Model is built and running

+ +

If the process didn’t have enough memory to +complete, there will be an error showing a problem with the ‘import_model.py’ +script execution. You can restart your computer and try it again and/or use a +smaller model.

To see if everything is working properly, you can open the url, Run Docker

-

Figure 10: ModHeader Chrome extension to add API key to -Authorization header

+

Figure 10: ModHeader Chrome extension to +add API key to Authorization header

 

The exact value to add to the header can be found in the -settings.py file located in the Docker Project Folder.

+settings.py file located in the Docker Project Folder, but will be something +like:

-

Once this is complete, then you are ready to connect the -NLLB Translator EncConverter to this service. Return to step  to the right of the address bar in the +browser) and uncheck the box next where it says Authorization in Figure 10 +above, so it isn’t used for all your internet traffic.

+ +

Once this is complete, then you are ready to connect the +NLLB Translator EncConverter to this service. Return to step (4) @@ -2261,12 +2339,13 @@

Saving the

By default, if you click the Apply or OK buttons, the configured converter will be returned to the client application as -a temporary converter for temporary use. Once the client application (e.g. FieldWorks or Word) is -closed or releases the converter, it will no longer be available. If you want -the converter to be permanently available to client applications, then you must -explicitly add it to the System Repository using -the Save in System Repository button.

+a temporary converter for temporary use. Once the client application (e.g. FieldWorks or Word) is closed or releases the converter, it will no +longer be available. If you want the converter to be permanently available to +client applications, then you must explicitly add it to the System Repository using the Save in System +Repository button.

When you click this button, the following dialog box will be displayed to query for a friendly name by diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/filelist.xml b/redist/Help/NLLB_Translate_Plug-in_About_box_files/filelist.xml index d9773b3d..71ff85ce 100644 --- a/redist/Help/NLLB_Translate_Plug-in_About_box_files/filelist.xml +++ b/redist/Help/NLLB_Translate_Plug-in_About_box_files/filelist.xml @@ -8,20 +8,14 @@ - - - - - - - + diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box_files/image010.jpg b/redist/Help/NLLB_Translate_Plug-in_About_box_files/image010.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f6fe8c07ee5558c14b0b16cad2e9f870dba745a GIT binary patch literal 1653 zcmex=cRarq{j0R}-11{VfTW=16jCP7AKLB{__7~~lk7+Ha?1vwZB7@3$^SlQS)IJvli z3bqO`FflSSGqEtUva+xMRo4RL8CV2ag%k}P*@OcV*_8@Kj2b5{ECr+Na zbot8FYu9hwy!G(W<0ns_J%91?)yGetzkL1n{m0K=Ab&A3Fhjfr_ZgbM1cClyVqsxs zVF&q(k*OSrnFU!`6%E;h90S=C3x$=88aYIqCNA7~kW<+>=!0ld(M2vX6_bamA3o-bN$j*f_@b&XR?E`ueBKwvqAtHJTNnae zML?KQ^!Ts+$9Bp~|7S?APhEfe&v|R!Z?!Xj|9F2}R(n%|q=zkUYF3o%x&_^`U$~7l zPd&G(Q);lOU7MGi)_$hVWA2BG?}N;%1ZRCctNr%=&5QM!Z+?ece=B)?{H1s4(#UvE zp6O<4{;e%rDu;GTlCpC zTcq#)Epuj_5TOEjS>L$-3@vr%|5az%|1jF|pW)F9X78;2hw@XcHvMOKD8KnX!@OJl z|9IBf|JY@Z%4N8+h&oDk-Ys`;I`42LFZZ3P$Smo|6t{mDcUUAWX>R)QN_)`)p8Y)k z8BVNTQh$Al{V#@9QN{k>R=;lDvVT^{q=bIe`|sj;8&=Ie$1id2;N`WkAI|^j+U5SY z()mBb0)Fy*}bjjH&?9lLYM6F@bk<4mmL+3ymRh^l&9C` z1y04i?J~{xf4Hwa%-=QNJa1RYv3nd(OC~Jo-m$<&C_sUooyEB9(boB1TZ-rQE%AQN zJ89Fyk3BtdMplgnPo9tJ|IK&YT*A{SMtjXf&L@Hs?pJf}&QMpM!1&}cOUU$?U9Eaz zzP4c%EqN={bau;j@H|n}?pPpAv>novB!QRSV? z^Enq-o!8u5t-Et$&%K#@CN(|&p8P~ly6(PZ(options.Headers, StringComparer.OrdinalIgnoreCase); - if (!headers.ContainsKey("Authorization")) + if (!String.IsNullOrEmpty(authKey) && !headers.ContainsKey("Authorization")) { headers.Add("Authorization", authKey); } diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs index 5c9f5088..1e0aa1f3 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs @@ -20,6 +20,7 @@ public partial class NllbTranslatorAutoConfigDialog : AutoConfigDialog { private readonly ComboBoxItem SourceLanguageNameMustBeConfigured = new ComboBoxItem { Display = "Select Source Language" }; private readonly ComboBoxItem TargetLanguageNameMustBeConfigured = new ComboBoxItem { Display = "Select Target Language" }; + private string ModelNameSuffix = String.Empty; // so we can add it to the friendly name -- but only works if the user edits (which they should do, but...) public NllbTranslatorAutoConfigDialog ( @@ -82,7 +83,7 @@ bool bIsInRepository if (!String.IsNullOrEmpty(apiKey) && !String.IsNullOrEmpty(endpoint)) GetLanguagesSupportedAndInitializeComboBoxes(false, apiKey, endpoint); else - buttonConfigureNllbModel.Enabled = false; // until the path is chosen + buttonConfigureNllbModel.Enabled = !String.IsNullOrEmpty(DockerProjectFolderPath); // until the path is chosen comboBoxSourceLanguages.SelectedItem = SourceLanguageNameMustBeConfigured; comboBoxTargetLanguages.SelectedItem = TargetLanguageNameMustBeConfigured; @@ -205,9 +206,10 @@ protected override string DefaultFriendlyName { var selectedSourceLanguage = (ComboBoxItem)comboBoxSourceLanguages.SelectedItem; var selectedTargetLanguage = (ComboBoxItem)comboBoxTargetLanguages.SelectedItem; - return $"Nllb Translate {selectedSourceLanguage} to {selectedTargetLanguage}"; + return $"NLLB{ModelNameSuffix} Translate {selectedSourceLanguage} to {selectedTargetLanguage}"; } - } + + } ///

/// Initialize the source and possibly target language combo boxes with the translation languages possible. @@ -274,9 +276,10 @@ private void ButtonSetNllbTranslateApiKey_Click(object sender, EventArgs e) Properties.Settings.Default.Save(); m_aEC = null; // reset the associated EncConverter instance so it'll get rebuilt w/ the new parameters + ModelNameSuffix = dlg.ModelNameSuffix; // so we can add it to the DefaultFriendlyName - // in case something changed, reinitialize the combo boxes - GetLanguagesSupportedAndInitializeComboBoxes(m_bInitialized, dlg.TranslatorApiKey, dlg.Endpoint); + // in case something changed, reinitialize the combo boxes + GetLanguagesSupportedAndInitializeComboBoxes(m_bInitialized, dlg.TranslatorApiKey, dlg.Endpoint); } } diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs index 01b1cbdf..5c1bb97f 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs @@ -84,7 +84,9 @@ public Translator NllbTranslator }, }; var apiKey = ApiKey ?? NllbTranslatorApiKey; - _nllbTranslator = new Translator(NllbAuthenticationPrefix + apiKey, options); + if (!String.IsNullOrEmpty(apiKey)) + apiKey = NllbAuthenticationPrefix + apiKey; + _nllbTranslator = new Translator(apiKey, options); } return _nllbTranslator; } @@ -98,19 +100,18 @@ public static string NllbTranslatorApiKey if (HasValidEnvironmentVariable(EnvVarNameKey, out string overrideKey)) return overrideKey; - var key = !String.IsNullOrEmpty((overrideKey = Properties.Settings.Default.NllbTranslatorKeyOverride)) - ? overrideKey - : Properties.Settings.Default.NllbTranslatorKey; + var key = Properties.Settings.Default.NllbTranslatorKeyOverride; #if encryptingNewCredentials var translatorKey = EncryptionClass.Encrypt(key); #endif - return EncryptionClass.Decrypt(key); + return String.IsNullOrEmpty(key) ? String.Empty : EncryptionClass.Decrypt(key); } set { - var translatorKey = !String.IsNullOrEmpty(value) - ? EncryptionClass.Encrypt(value) + var trimmedValue = value?.Trim(); + var translatorKey = !String.IsNullOrEmpty(trimmedValue) + ? EncryptionClass.Encrypt(trimmedValue) : null; Properties.Settings.Default.NllbTranslatorKeyOverride = translatorKey; } diff --git a/src/EcTranslators/NllbTranslator/QueryForEndpointAndApiKey.cs b/src/EcTranslators/NllbTranslator/QueryForEndpointAndApiKey.cs index 7bb1dd20..3487ed2b 100644 --- a/src/EcTranslators/NllbTranslator/QueryForEndpointAndApiKey.cs +++ b/src/EcTranslators/NllbTranslator/QueryForEndpointAndApiKey.cs @@ -192,9 +192,13 @@ private void buttonOK_Click(object sender, System.EventArgs e) // the server.py file File.WriteAllText(Path.Combine(_pathToDockerProjectFolder, FileNamePyServer), Properties.Resources.server); - // the settings.py file - var settingsFileContents = String.Format(Properties.Resources.settings, - $"'{NllbTranslatorEncConverter.NllbAuthenticationPrefix + TranslatorApiKey}'", Port, $"'{ModelName}'"); + // the settings.py file + var translatorApiKey = TranslatorApiKey?.Trim(); + if (!String.IsNullOrEmpty(translatorApiKey)) + translatorApiKey = NllbTranslatorEncConverter.NllbAuthenticationPrefix + translatorApiKey; + + var settingsFileContents = string.Format(Properties.Resources.settings, + $"'{translatorApiKey}'", Port, $"'{ModelName}'"); File.WriteAllText(Path.Combine(_pathToDockerProjectFolder, FileNamePySettings), settingsFileContents); MessageBox.Show($"If you have Docker installed and a recent version of Powershell (see instructions on the About tab), open a Powershell Window and run the two 'docker' commands listed in the '{pathToReadme}' file to build the NLLB Docker project (or run them in the '{pathToPsScript}' script if you know how to enable running scripts from the internet). When finished, return to this message and click 'OK' to connect to the launched endpoint and continue.", diff --git a/src/EcTranslators/Properties/Settings.Designer.cs b/src/EcTranslators/Properties/Settings.Designer.cs index 1978fa67..806027e0 100644 --- a/src/EcTranslators/Properties/Settings.Designer.cs +++ b/src/EcTranslators/Properties/Settings.Designer.cs @@ -251,18 +251,9 @@ public string AzureOpenAiKeyLocationDialogInstructionUrl { } } - [global::System.Configuration.ApplicationScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1")] - public string NllbTranslatorKey { - get { - return ((string)(this["NllbTranslatorKey"])); - } - } - [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] + [global::System.Configuration.DefaultSettingValueAttribute("N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1")] public string NllbTranslatorKeyOverride { get { return ((string)(this["NllbTranslatorKeyOverride"])); diff --git a/src/EcTranslators/Properties/Settings.settings b/src/EcTranslators/Properties/Settings.settings index dd482165..449364c6 100644 --- a/src/EcTranslators/Properties/Settings.settings +++ b/src/EcTranslators/Properties/Settings.settings @@ -55,11 +55,8 @@ <string>UseSystemPrompt: Translate from Hindi into English.</string> </ArrayOfString> - - N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1 - - + N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1 http://localhost:8000 diff --git a/src/EcTranslators/app.config b/src/EcTranslators/app.config index e9de1361..7a010cdb 100644 --- a/src/EcTranslators/app.config +++ b/src/EcTranslators/app.config @@ -141,7 +141,7 @@ - + N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1 @@ -153,9 +153,6 @@ - - N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1 - http://localhost:8000 From 41e42c8858edfc92d1bc77778ee50d4f68a9d0fd Mon Sep 17 00:00:00 2001 From: bobeaton Date: Thu, 9 Nov 2023 09:37:22 -0600 Subject: [PATCH 075/113] fixed a bug where we were grabbing the wrong api key and endpoint if the user switched to a different one and then edited an earlier one. Also updated the comments in the unit test for NLLB for the new approach --- .../NllbTranslatorAutoConfigDialog.cs | 14 ++++++++++++-- src/TestEncCnvtrs/TestEcTranslators.cs | 17 ++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs index 1e0aa1f3..4329e968 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorAutoConfigDialog.cs @@ -263,7 +263,17 @@ private void ButtonSetNllbTranslateApiKey_Click(object sender, EventArgs e) return; } - using var dlg = new QueryForEndpointAndApiKey(dockerProjectFolderPath, NllbTranslatorApiKey, NllbTranslatorEndpoint); + var apiKey = NllbTranslatorApiKey; + var endpoint = NllbTranslatorEndpoint; + if (m_aEC != null) + { + var theTranslator = (NllbTranslatorEncConverter)m_aEC; + apiKey = theTranslator.ApiKey; + endpoint = theTranslator.Endpoint; + } + + + using var dlg = new QueryForEndpointAndApiKey(dockerProjectFolderPath, apiKey, endpoint); if (dlg.ShowDialog() == DialogResult.OK) { // if the user configures a model, then save the API Key and Endpoint for any new converters they create @@ -271,7 +281,7 @@ private void ButtonSetNllbTranslateApiKey_Click(object sender, EventArgs e) // whether they build the model (successfully) or not) Properties.Settings.Default.NllbTranslatorPathToDockerProject = dockerProjectFolderPath; NllbTranslatorApiKey = dlg.TranslatorApiKey; - var endpoint = dlg.Endpoint; + endpoint = dlg.Endpoint; NllbTranslatorEndpoint = (endpoint == Properties.Settings.Default.NllbTranslatorEndpoint) ? null : endpoint; Properties.Settings.Default.Save(); diff --git a/src/TestEncCnvtrs/TestEcTranslators.cs b/src/TestEncCnvtrs/TestEcTranslators.cs index d27b50e1..595993cb 100644 --- a/src/TestEncCnvtrs/TestEcTranslators.cs +++ b/src/TestEncCnvtrs/TestEcTranslators.cs @@ -202,19 +202,22 @@ public void CleanupForClass() private const string NllbConverterFriendlyName = "NllbTranslator"; /// - /// To run this test, you need to have the https://github.com/Nateowami/NLLB-demo repo clones, - /// and built into a docker container and running on your local machine + /// To run this test, you need to go thru the instructions in have the $(SolutionDir)redist\Help\NLLB_Translate_Plug-in_About_box.htm + /// file to create a docker container for the NLLB 600m model and run it on your local machine. + /// Two additional notes: + /// 1) have no api key in the NLLB Model Config dialog (or set up an env var with it--see TestAzureOpenAiConverter for an eg) + /// 2) Change the @"D:\NLLB\test" path to wherever you chose as the Docker Project folder. /// - /// - /// - /// + /// ConverterIdentifier of the NLLB converter to be used to convert the text + /// The text to be translated + /// The expected translation [Test] - [TestCase("hin_Deva;eng_Latn", + [TestCase(@"D:\NLLB\test;hin_Deva;eng_Latn", @"फिर एक स्‍वर्गदूत ने मुझसे कहा, ""इस बात को लिख ले: वे धन्य हैं, जिनको मेमने के विवाह के भोज का निमन्‍त्रण है। यह परमेश्वर के सच्‍चे बोल हैं।", @"Then an angel said to me, ""Write: Blessed are those who are invited to the wedding banquet of the Lamb"". These are the true words of God.")] - [TestCase("hin_Deva;eng_Latn", + [TestCase(@"D:\NLLB\test;hin_Deva;eng_Latn", "वे जानते हैं कि परमेश्वर का अस्तित्व है और यह सब कुछ उनके लिए ही बनाया है। परंतु फिर भी न तो वे परमेश्वर का कोई सम्‍मान, और न ही तो उसका धन्यवाद करते हैं। इसलिए उनकी आँखें में पर्दा पड़ गया है, और परमेश्वर के विषय में उनका जो विचार है, वह गलत हो चुका है।", "They know that God exists and that everything was made for them. Yet they do not give glory to God or give him thanks. Their minds are blinded and their thoughts are in error.")] public void TestNllbConverter(string converterSpec, string testInput, string testOutput) From 0d08bf0cf7cebefc96ff1416929c1b2cdb54101f Mon Sep 17 00:00:00 2001 From: bobeaton Date: Thu, 9 Nov 2023 11:02:26 -0600 Subject: [PATCH 076/113] add the ability to copy sections of text from one of the translations to the editable box via Ctrl+Down or right-click in the possible target boxes. --- .../BackTranslationHelperCtrl.cs | 37 ++++++++++- .../BackTranslationHelperCtrl.designer.cs | 64 ++++++++++++------- .../BackTranslationHelperCtrl.resx | 3 + 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs index 6340eff1..61118a85 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs @@ -649,7 +649,7 @@ private string PreprocessTargetData(string targetDataOrig) return targetData; } - private void SetStatusBox(string value) + private void SetStatusBox(string value) { toolStripTextBoxStatus.Text = value; toolStripTextBoxStatus.BackColor = String.IsNullOrEmpty(value) @@ -1140,7 +1140,40 @@ private void TextBoxTargetBackTranslation_PreviewKeyDown(object sender, PreviewK } } - private static bool _ignoreChange; + private void TextBoxPossibleTargetTranslation_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e) + { + if (e.KeyData == (Keys.Control | Keys.Down)) + CopySelectedTextToTargetTranslationTextBox(sender); + } + + private void TextBoxPossibleTargetTranslation_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + CopySelectedTextToTargetTranslationTextBox(sender); + } + + private void CopySelectedTextToTargetTranslationTextBox(object sender) + { + // if the user has text selected in one of the possible translation text boxes and an insertion point in the target Translation text box + // AND if they press Ctrl+Down arrow, then copy that text down to the insertion point + var textBox = sender as TextBox; + var cursorPosition = textBoxTargetBackTranslation.SelectionStart; + var textToInsert = textBox.SelectedText; + var textToReplace = textBoxTargetBackTranslation.SelectedText; + if (!string.IsNullOrEmpty(textToInsert) && (cursorPosition >= 0)) + { + if (!String.IsNullOrEmpty(textToReplace)) + textBoxTargetBackTranslation.SelectedText = String.Empty; + + cursorPosition = textBoxTargetBackTranslation.SelectionStart; + textToReplace = textBoxTargetBackTranslation.Text; + textBoxTargetBackTranslation.Text = textBoxTargetBackTranslation.Text.Insert(cursorPosition, textToInsert); + textBoxTargetBackTranslation.SelectionStart = cursorPosition + textToInsert.Length; + textBoxTargetBackTranslation.Focus(); + } + } + + private static bool _ignoreChange; private void DisplayRighttoleftToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { _ignoreChange = true; diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs index 19b5c7aa..d902796a 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs @@ -81,7 +81,8 @@ private void InitializeComponent() this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.buttonPinToTop = new System.Windows.Forms.Button(); this.fontDialog = new System.Windows.Forms.FontDialog(); - this.menuStrip.SuspendLayout(); + this.contextMenuHideDefault = new System.Windows.Forms.ContextMenu(); + this.menuStrip.SuspendLayout(); this.tableLayoutPanel.SuspendLayout(); this.substitutionContextMenu.SuspendLayout(); this.SuspendLayout(); @@ -372,6 +373,9 @@ private void InitializeComponent() this.textBoxPossibleTargetTranslation1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.textBoxPossibleTargetTranslation1.Size = new System.Drawing.Size(548, 42); this.textBoxPossibleTargetTranslation1.TabIndex = 11; + this.textBoxPossibleTargetTranslation1.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation1.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation1.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; // // buttonFillTargetTextOption1 // @@ -408,11 +412,14 @@ private void InitializeComponent() this.textBoxPossibleTargetTranslation2.ReadOnly = true; this.textBoxPossibleTargetTranslation2.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.textBoxPossibleTargetTranslation2.Size = new System.Drawing.Size(548, 42); - this.textBoxPossibleTargetTranslation2.TabIndex = 11; - // - // buttonFillTargetTextOption2 - // - this.buttonFillTargetTextOption2.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; + this.textBoxPossibleTargetTranslation2.TabIndex = 12; + this.textBoxPossibleTargetTranslation2.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation2.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation2.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; + // + // buttonFillTargetTextOption2 + // + this.buttonFillTargetTextOption2.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; this.buttonFillTargetTextOption2.Location = new System.Drawing.Point(675, 157); this.buttonFillTargetTextOption2.Name = "buttonFillTargetTextOption2"; this.buttonFillTargetTextOption2.Size = new System.Drawing.Size(23, 23); @@ -444,11 +451,14 @@ private void InitializeComponent() this.textBoxPossibleTargetTranslation3.ReadOnly = true; this.textBoxPossibleTargetTranslation3.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.textBoxPossibleTargetTranslation3.Size = new System.Drawing.Size(548, 42); - this.textBoxPossibleTargetTranslation3.TabIndex = 11; - // - // buttonFillTargetTextOption3 - // - this.buttonFillTargetTextOption3.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; + this.textBoxPossibleTargetTranslation3.TabIndex = 13; + this.textBoxPossibleTargetTranslation3.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation3.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation3.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; + // + // buttonFillTargetTextOption3 + // + this.buttonFillTargetTextOption3.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; this.buttonFillTargetTextOption3.Location = new System.Drawing.Point(675, 205); this.buttonFillTargetTextOption3.Name = "buttonFillTargetTextOption3"; this.buttonFillTargetTextOption3.Size = new System.Drawing.Size(23, 23); @@ -480,11 +490,14 @@ private void InitializeComponent() this.textBoxPossibleTargetTranslation4.ReadOnly = true; this.textBoxPossibleTargetTranslation4.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.textBoxPossibleTargetTranslation4.Size = new System.Drawing.Size(548, 42); - this.textBoxPossibleTargetTranslation4.TabIndex = 12; - // - // buttonFillTargetTextOption4 - // - this.buttonFillTargetTextOption4.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; + this.textBoxPossibleTargetTranslation4.TabIndex = 14; + this.textBoxPossibleTargetTranslation4.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation4.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation4.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; + // + // buttonFillTargetTextOption4 + // + this.buttonFillTargetTextOption4.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; this.buttonFillTargetTextOption4.Location = new System.Drawing.Point(675, 253); this.buttonFillTargetTextOption4.Name = "buttonFillTargetTextOption4"; this.buttonFillTargetTextOption4.Size = new System.Drawing.Size(23, 23); @@ -661,10 +674,14 @@ private void InitializeComponent() // this.fontDialog.Font = new System.Drawing.Font("Arial Unicode MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.fontDialog.ShowColor = true; - // - // BackTranslationHelperCtrl - // - this.AutoSize = true; + // + // contextMenuHideDefault + // + this.contextMenuHideDefault.Name = "contextMenuHideDefault"; + // + // BackTranslationHelperCtrl + // + this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.buttonPinToTop); this.Controls.Add(this.tableLayoutPanel); @@ -681,9 +698,9 @@ private void InitializeComponent() } - #endregion + #endregion - private System.Windows.Forms.MenuStrip menuStrip; + private System.Windows.Forms.MenuStrip menuStrip; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; private System.Windows.Forms.TextBox textBoxTargetBackTranslation; private System.Windows.Forms.Button buttonWriteTextToTarget; @@ -732,5 +749,6 @@ private void InitializeComponent() private System.Windows.Forms.Label labelForPossibleTargetTranslation2; private System.Windows.Forms.Label labelForPossibleTargetTranslation3; private System.Windows.Forms.Label labelForPossibleTargetTranslation4; - } + private System.Windows.Forms.ContextMenu contextMenuHideDefault; + } } diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.resx b/src/BackTranslationHelper/BackTranslationHelperCtrl.resx index f28e895e..609543ec 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.resx +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.resx @@ -129,4 +129,7 @@ 213, 20 + + 511, 20 + \ No newline at end of file From 40cdabbf535d30baca7baeeaf21573496cdf7d05 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Thu, 9 Nov 2023 11:41:22 -0600 Subject: [PATCH 077/113] updated the help instructions for how to share an NLLB model across a network --- .../Help/NLLB_Translate_Plug-in_About_box.htm | 3911 +++++++++-------- 1 file changed, 2105 insertions(+), 1806 deletions(-) diff --git a/redist/Help/NLLB_Translate_Plug-in_About_box.htm b/redist/Help/NLLB_Translate_Plug-in_About_box.htm index b7a98530..ca68bbc6 100644 --- a/redist/Help/NLLB_Translate_Plug-in_About_box.htm +++ b/redist/Help/NLLB_Translate_Plug-in_About_box.htm @@ -5,1736 +5,1972 @@ xmlns="http://www.w3.org/TR/REC-html40"> - - - - - - - - -NLLB Translator - - - - - - - + + + + + + + + + NLLB Translator + + + + + + + + + + No Language Left color:#202124;background:white'>™ Translator to perform text processing within EncConverter-enabled applications. The NLLB Translator is currently a -local translation service, but is expected to be -online as well with the larger data models by the end of 2024. It can be used -to perform language translation between a growing number of languages (see here for specific supported languages).

The NLLB Translator, which is available to EncConverter-enabled applications, -currently requires a number of complex additional -steps to use beyond simply installing the EncConverter. You may need to update PowershellNo Language Left target="_blank">commands in Powershell to build the Docker container, which downloads the NLLB model and other prerequisites (~2.5 GB) and creates an interface to the model. Finally, you need to run the Docker container to allow -the NLLB Translator EncConverter to access the model. Instructions for these prerequisites -are discussed below. It is suggested that you restart your computer before -doing these steps in order to free up as much memory -as possible.

+the NLLB Translator EncConverter to access the model. Instructions for these +prerequisites are discussed below. It is suggested that you restart your +computer before doing these steps in order to free up as much memory as +possible.

-

-Click to Open this page in a Browser window -

+

Click to Open this page in a Browser window

Virtualization Check

@@ -1862,7 +2096,7 @@

Update Powershell winget

+float:none;word-spacing:0px'> winget

If this doesn’t work, then you can install the latest version of Powershell by following the instructions on

+src="NLLB_Translate_Plug-in_About_box_files/image008.jpg" v:shapes="_x0000_i1036">

Figure Add button:

+src="NLLB_Translate_Plug-in_About_box_files/image012.jpg" v:shapes="Picture_x0020_4">

Figure 4: Select and Add New Converter type

+yes'>4: Select and Add New Converter type

 

@@ -2115,27 +2349,24 @@

< style='font:7.0pt "Times New Roman"'>      This edit box is to enter the endpoint through which the model can be accessed from your computer. If you only plan to use your model -from your own computer, you can just keep the default value. If you plan to -access it from another computer on your local network, you will enter the IP -address of the computer that is hosting the model along with the port to use (e.g. http://192.168.62.154:8000).

- -

Note that if you plan to share your -model with other computers, you may need to make a change to the firewall on -the computer that is hosting the model to allow access to port 8000 (see this -page for hints on how to do this).

+from your own computer, you can just keep the default value (http://localhost:8000). If you want to share a +model with multiple computers on your local network, see the ‘Sharing +a model with other computers on a local network’ section below.

It’s also possible to use a -different port to access the model (i.e. in place of the -value 8000 above). If you plan to host multiple NLLB models at the same time, -you will have to use a different port for each one to access them simultaneously. -The port number can be whatever you want, but again, you might need to adjust -the firewall to allow inbound traffic for whatever port you choose.

+different port to access the model (i.e. in place of the value 8000 above). If +you plan to host multiple NLLB models at the same time, you will have to use a +different port for each one to access them simultaneously. The port number can +be whatever you want, but again, you might need to adjust the firewall to allow +inbound traffic for whatever port you choose.

4)< alt="A screenshot of a computer error Description automatically generated" v:shapes="Picture_x0020_8">

-

Build Docker -Container

+

Build +Docker Container

The remaining steps will be run in a Powershell window. Suppose the Model Configuration files were installed to the Build Docker which model you choose):

docker build -t nllb-600m .

+font-family:Consolas;color:#006881;background:#F2F2F2'>docker build -t +nllb-600m .

This step can take a long time, because it must download the NLLB model and several other prerequisites (>2.5 GB for the smallest @@ -2207,12 +2438,12 @@

Build Docker

Note: there is a Powershell script named buildDocker.ps1 that is also created in the Docker Project Folder that you could run in -Powershell to accomplish this and the next step. But if your computer is initialized -to block unknown Powershell scripts, the script won’t execute +Powershell to accomplish this and the next step. But if your computer is +initialized to block unknown Powershell scripts, the script won’t execute and you’ll have to enter them manually as shown above.

-

Run Docker -Container

+

Run +Docker Container

The final step to prepare the NLLB model is to execute the following command in Powershell after the docker build step completes (your @@ -2220,31 +2451,30 @@

Run Docker

docker run -p 8000:8000 -nllb-600m

+nllb-600m

Once this command is finished, your powershell should look something like this:

A screenshot of a computer program

Description automatically generated

+v:shapes="Picture_x0020_9">

Figure 8: Powershell after NLLB Model is built and running

+yes'>8: Powershell after NLLB Model is built and running

If the process didn’t have enough memory to -complete, there will be an error showing a problem with the ‘import_model.py’ -script execution. You can restart your computer and try it again and/or use a -smaller model.

+complete, there will be an error showing a problem with the +‘import_model.py’ script execution. You can restart your computer +and try it again and/or use a smaller model.

To see if everything is working properly, you can open the url, Run Docker

NOTE: If you created an API Key in the Model Configuration Dialog above, then you would need to add that key (along with the prefix, “SIL-NLLB-Auth-Key , -note the following space) to the Authorization -header in your browser to see this web page. For example, most browsers support -the extension, ModHeader, which allows -you to enter key value pairs in the Request Header like this:

+class=MsoSubtleReference>SIL-NLLB-Auth-Key, note the following space) to the Authorization header in your browser to see +this web page. For example, most browsers support the extension, ModHeader, which allows you to enter key value +pairs in the Request Header like this:

Run Docker section above and click OK to connect to the model endpoint and query for languages in the Setup dialog.

+

Sharing +a model with other computers on a local network

+ +

If you have multiple computers that want to share a model, +you can host it from one computer and share the endpoint with other computers +on your local network by configuring the latter to use the IP address of the +hosting machine as the endpoint rather than http://localhost:8000. +

+ +

On the computer that is hosting the model, during the Model Configuration +Dialog +step above, you would use http://localhost:8000, +for example, as the endpoint and build the model using the instructions in the Build Docker Container +and Run Docker Container +sections above.

+ +

And from the other computers on your local network, during +the Model Configuration +Dialog +step above, you would use the IP address of the machine with the model as the +endpoint (e.g. http://192.168.62.154:8000). +And then there’s no need to build the model on that computer (i.e. for +the non-hosting machines, ignore the instructions in the Build Docker Container +and Run Docker Container +sections above).

+ +

Also note that if you share a model with other computers, +you may need to make a change to the firewall on the computer that is hosting +the model to allow access to port 8000 (or whichever port you choose) from the +network. See this +page for hints on how to do this.

+

Saving the converter in the System Repository:

By default, if you click the Apply or OK buttons, the configured converter will be returned to the client application as -a temporary converter for temporary use. Once the client application (e.g. FieldWorks or Word) is closed or releases the converter, it will no -longer be available. If you want the converter to be permanently available to -client applications, then you must explicitly add it to the System Repository using the Save in System -Repository button.

+a temporary converter for temporary use. Once the client application (e.g. FieldWorks or Word) is +closed or releases the converter, it will no longer be available. If you want +the converter to be permanently available to client applications, then you must +explicitly add it to the System Repository using +the Save in System Repository button.

When you click this button, the following dialog box will be displayed to query for a friendly name by From db2d94c6091956896ff5038d3c5e388a90ec2e2a Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sun, 12 Nov 2023 11:08:47 -0600 Subject: [PATCH 078/113] clear out the output of the test page if the test button is pressed. Also add support for manually selecting all if Ctrl+A is pressed in an EcTextBox (don't know why the base for OnPreviewKeyDown isn't doing that...) --- src/EncCnvtrs/AutoConfigDialog.cs | 3 ++- src/EncCnvtrs/EcTextBox.cs | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/EncCnvtrs/AutoConfigDialog.cs b/src/EncCnvtrs/AutoConfigDialog.cs index 15b43828..2629db03 100755 --- a/src/EncCnvtrs/AutoConfigDialog.cs +++ b/src/EncCnvtrs/AutoConfigDialog.cs @@ -783,7 +783,8 @@ protected void TestTabInputChanged() private void buttonTest_Click(object sender, EventArgs e) { Util.DebugWriteLine(this, "BEGIN"); - IEncConverter aEC = InitializeEncConverter; + ecTextBoxOutput.Text = String.Empty; // clear out any previous contents + IEncConverter aEC = InitializeEncConverter; if (aEC != null) { try diff --git a/src/EncCnvtrs/EcTextBox.cs b/src/EncCnvtrs/EcTextBox.cs index 1e46a348..05554c1b 100755 --- a/src/EncCnvtrs/EcTextBox.cs +++ b/src/EncCnvtrs/EcTextBox.cs @@ -11,7 +11,6 @@ public EcTextBox() { Util.DebugWriteLine(this, "Default Font " + this.Font.Name + ", Size " + this.Font.Size.ToString()); - //this.Font = new System.Drawing.Font("Arial", 11); } protected override void OnPreviewKeyDown(System.Windows.Forms.PreviewKeyDownEventArgs e) @@ -20,7 +19,12 @@ protected override void OnPreviewKeyDown(System.Windows.Forms.PreviewKeyDownEven e.KeyValue, e.KeyCode, e.KeyData)); if (e.Alt && (e.KeyCode == System.Windows.Forms.Keys.X)) ConvertNumberToChar(false); - base.OnPreviewKeyDown(e); + + // don't know why, but the base.OnPreviewKeyDown doesn't do 'select all' + if (e.KeyData == (System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)) + SelectAll(); + else + base.OnPreviewKeyDown(e); } protected void ConvertNumberToChar(bool bIsLegacy) From a282953bb9b94efaad4aa1b33dbf9d13aa74be7f Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sun, 12 Nov 2023 19:42:57 -0600 Subject: [PATCH 079/113] add a protocol to cause the NLLB Translator to start to split text to translate into smaller chunks. If it gets too big, it starts to leave stuff out. --- .../NllbTranslatorEncConverter.cs | 134 +++++++++++++++++- .../Properties/Settings.Designer.cs | 18 +++ .../Properties/Settings.settings | 6 + src/EcTranslators/app.config | 6 + 4 files changed, 157 insertions(+), 7 deletions(-) diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs index 5c1bb97f..dde601f1 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs @@ -15,6 +15,7 @@ using System.Windows.Forms; using SilEncConverters40.EcTranslators.Properties; using System.Collections; +using System.Text.RegularExpressions; namespace SilEncConverters40.EcTranslators.NllbTranslator { @@ -45,6 +46,8 @@ public class NllbTranslatorEncConverter : TranslatorConverter public const string EnvVarNameEndPoint = "EncConverters_NllbEndpoint"; public const string EnvVarNameKey = "EncConverters_NllbApiKey"; + public const string SplitSentencesPrefix = @"\SplitSentences "; // send for conversion: \SplitSentences ON and \SplitSentences OFF + #endregion Const Definitions #region Member Variable Definitions @@ -55,6 +58,13 @@ public class NllbTranslatorEncConverter : TranslatorConverter public string ApiKey; // always clear text public string Endpoint; + public Regex SentenceSplitter = new Regex(Properties.Settings.Default.NllbSentenceFinalPunctuationRegex); + public bool IsSplitSentences = Properties.Settings.Default.NllbProcessSentenceBySentence; + + public int RepeatsOfLastInputString { get; set; } = 0; + public string LastInputString { get; set; } + public int MaxTokensPerSentence { get; set; } + private static bool HasValidEnvironmentVariable(string envVarName, out string parameter) { return !string.IsNullOrEmpty((parameter = Environment.GetEnvironmentVariable(envVarName))); @@ -84,9 +94,9 @@ public Translator NllbTranslator }, }; var apiKey = ApiKey ?? NllbTranslatorApiKey; - if (!String.IsNullOrEmpty(apiKey)) - apiKey = NllbAuthenticationPrefix + apiKey; - _nllbTranslator = new Translator(apiKey, options); + if (!String.IsNullOrEmpty(apiKey)) + apiKey = NllbAuthenticationPrefix + apiKey; + _nllbTranslator = new Translator(apiKey, options); } return _nllbTranslator; } @@ -109,7 +119,7 @@ public static string NllbTranslatorApiKey } set { - var trimmedValue = value?.Trim(); + var trimmedValue = value?.Trim(); var translatorKey = !String.IsNullOrEmpty(trimmedValue) ? EncryptionClass.Encrypt(trimmedValue) : null; @@ -265,11 +275,121 @@ ref int rnOutLen // here's our input string var strInput = new string(caIn); - var strOutput = String.IsNullOrEmpty(strInput) - ? strInput - : CallNllbTranslator(strInput).Result; + var strOutput = DoConvert(strInput); StringToProperByteStar(strOutput, lpOutBuffer, ref rnOutLen); + return; + } + + protected string DoConvert(string strInput) + { + // if we're not already splitting sentences, see if we're getting the same string over and over again + if ((LastInputString == strInput) && (RepeatsOfLastInputString++ > 0)) + { + // ... on the 3rd time of getting the same string, start the splitting of sentences and processing them separately + // to see if that helps. Here's an example of one that the facebook-1.3G model seems to lose its way with: + // (केवल ये शहीद और न्याय करने वाले लोग हजार वर्षों वाले उस युग के आरंभ में पुनर्जीवित हो जाएँगे। इस बार जीवित होने को “पहला जीवित होना” कहते हैं। बाकि जो मरे हुए हैं, परमेश्वर उन सबको तब तक पुनर्जीवित नहीं करेगा, जब तक उस हजार वर्षों वाले युग का अंत नहीं होगा।) + // litBt: (Only these martyrs and judge-doing ones will become alive again in the beginning of that thousand year era. This time of becoming alive is called the “first resurrection.” The remaining (ones) who have died, God will not make them alive again until the end of that thousand years era happens.) + // 1.3G model (before splitting sentences): + // (The first resurrection is the first.) The rest of the dead will not be raised until the thousand years are ended. + // 1.3G model (after splitting sentences): + // (Only these martyrs and judges will be resurrected at the beginning of the millennial age. This resurrection is called the first resurrection.) (The rest of the dead will not be raised until the thousand years are over.) + IsSplitSentences = true; + + // start w/ 1 less than the current, so we'll likely do a split right away + MaxTokensPerSentence = WordCount(strInput) - RepeatsOfLastInputString; + + // if the user keeps doing this until it goes negative, then just start over + if (MaxTokensPerSentence < 0) + { + SetSplitSentences(false); // start over + } + System.Diagnostics.Debug.WriteLine($"NllbEncConverter: RepeatsOfLastInputString: {RepeatsOfLastInputString}, convert the string, \"{SplitSentencesPrefix} ON\" (or OFF), to turn on (or off) splitting sentences"); + } + else + { + LastInputString = strInput; + if (strInput.StartsWith(SplitSentencesPrefix)) + { + SetSplitSentences(strInput.Substring(Math.Min(strInput.Length, SplitSentencesPrefix.Length))?.StartsWith("ON") ?? false); + } + } + + var toAdd = default((int, string)); + var sentences = new List<(int WordCount, string Sentence)>(); + if (IsSplitSentences) + { + SentenceSplitter.Replace(strInput, LimitSentenceLength); + if (sentences.Sum(s => s.Sentence.Length) < strInput.Length) + { + var accumulatedSentences = String.Join(String.Empty, sentences.Select(s => s.Sentence)); + System.Diagnostics.Debug.Assert(strInput.Contains(accumulatedSentences)); + var addlInput = strInput.Substring(accumulatedSentences.Length); // add the remaining bit that didn't end in a sentence final puntuation + var lastSentence = sentences.LastOrDefault(); + if (lastSentence != default) + { + sentences.Remove(lastSentence); // remove it here, so it can be added back combined later + addlInput = lastSentence.Sentence + addlInput; + } + toAdd = (WordCount(addlInput), addlInput); + } + } + else + toAdd = (WordCount(strInput), strInput); + + if (toAdd != default) + sentences.Add(toAdd); + + var strOutput = String.Empty; + foreach (var sentence in sentences.Select(s => s.Sentence)) + { + var output = String.IsNullOrEmpty(sentence.Trim()) + ? sentence + : CallNllbTranslator(sentence).Result; + + // make sure the space isn't lost between the sentences + if ((strOutput.LastOrDefault() != default) && (output?.First() != ' ')) + strOutput += ' '; + + strOutput += output; + } + + return strOutput; + + + string LimitSentenceLength(Match match) + { + var sentence = match.ToString(); + var wordCount = WordCount(sentence); + var lastSentence = sentences.LastOrDefault(); + + // if there is no last sentence or if it would go beyond the limit to add this one to its Sentence... + int combinedWordCount = wordCount; + if ((lastSentence == default((int, string))) || ((combinedWordCount = (wordCount + lastSentence.WordCount)) > MaxTokensPerSentence)) + { + sentences.Add((wordCount, sentence)); // ... make this new one the new last sentence + } + else + { + // otherwise, remove the current last sentence, and add this combined one back in + sentences.Remove(lastSentence); + var combinedSentence = lastSentence.Sentence + sentence; + sentences.Add((combinedWordCount, combinedSentence)); + } + return sentence; // always return the matched item, so we can see if we got the whole thing + } + + void SetSplitSentences(bool isSplitSentences) // expecting this to be either 'ON' or 'OFF' + { + IsSplitSentences = isSplitSentences; + RepeatsOfLastInputString = isSplitSentences ? 1 : 0; + System.Diagnostics.Debug.WriteLine($"NllbEncConverter: Sentence Splitting is {isSplitSentences}. Convert the same string again and it'll start up again w/ 1 less than the number of tokens in the next string sent for conversion."); + } + } + + private static int WordCount(string sentence) + { + return sentence.Split(new[] { ' ' }).Length; } private async Task CallNllbTranslator(string strInput) diff --git a/src/EcTranslators/Properties/Settings.Designer.cs b/src/EcTranslators/Properties/Settings.Designer.cs index 806027e0..320a682e 100644 --- a/src/EcTranslators/Properties/Settings.Designer.cs +++ b/src/EcTranslators/Properties/Settings.Designer.cs @@ -295,5 +295,23 @@ public string NllbTranslatorPathToDockerProject { this["NllbTranslatorPathToDockerProject"] = value; } } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("(.*?)([\\p{Po}-[,]])")] + public string NllbSentenceFinalPunctuationRegex { + get { + return ((string)(this["NllbSentenceFinalPunctuationRegex"])); + } + } + + [global::System.Configuration.ApplicationScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool NllbProcessSentenceBySentence { + get { + return ((bool)(this["NllbProcessSentenceBySentence"])); + } + } } } diff --git a/src/EcTranslators/Properties/Settings.settings b/src/EcTranslators/Properties/Settings.settings index 449364c6..5371ca51 100644 --- a/src/EcTranslators/Properties/Settings.settings +++ b/src/EcTranslators/Properties/Settings.settings @@ -67,5 +67,11 @@ + + (.*?)([\p{Po}-[,]]) + + + False + \ No newline at end of file diff --git a/src/EcTranslators/app.config b/src/EcTranslators/app.config index 7a010cdb..a82e9dd6 100644 --- a/src/EcTranslators/app.config +++ b/src/EcTranslators/app.config @@ -156,6 +156,12 @@ http://localhost:8000 + + (.*?)([\p{Po}-[,]]) + + + False + \ No newline at end of file From 086b51dee705f4a4346141bb705d27013a0f8c25 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sun, 12 Nov 2023 20:02:46 -0600 Subject: [PATCH 080/113] provide a way to hook into the NLLB 'SplitSentences' approach thru a menu item on the Settings menu of the BT Helper Ctrl. --- .../BackTranslationHelperCtrl.cs | 132 ++++++++----- .../BackTranslationHelperCtrl.designer.cs | 178 ++++++++++-------- .../BackTranslationHelperCtrl.resx | 12 +- 3 files changed, 186 insertions(+), 136 deletions(-) diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs index 61118a85..cfd07cb9 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs @@ -6,7 +6,6 @@ using System.Collections.Specialized; using System.Drawing; using System.Linq; -using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -17,6 +16,11 @@ public partial class BackTranslationHelperCtrl : UserControl { public const int MaxPossibleTargetTranslations = 4; // to add more, you have to add new lines like the one starting at row 2 + // I could make the EcTranslator project a dependency to this project and use NllbEncConverter.CstrDisplayName instead, but... + private const string NllbEncConverterDisplayName = "NLLB Translator"; + private const string NllbEncConverterSplitSentencesPrefix = @"\SplitSentences "; + + #region Member variables // the form in which this UserControl is embedded will initialize these public IBackTranslationHelperDataSource BackTranslationHelperDataSource; @@ -66,6 +70,7 @@ protected override void OnParentChanged(EventArgs e) private void SettingsToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { this.hideCurrentTargetTextToolStripMenuItem.Visible = (_model == null) || (_model.DisplayExistingTargetTranslation); + this.SentenceSplittingMenuItem.Enabled = TheTranslators.Any(t => t.Configurator?.ConfiguratorDisplayName == NllbEncConverterDisplayName); } private void TargetBackTranslation_MouseWheel(object sender, MouseEventArgs e) @@ -649,7 +654,7 @@ private string PreprocessTargetData(string targetDataOrig) return targetData; } - private void SetStatusBox(string value) + private void SetStatusBox(string value) { toolStripTextBoxStatus.Text = value; toolStripTextBoxStatus.BackColor = String.IsNullOrEmpty(value) @@ -879,6 +884,17 @@ private void HideColumn1LabelsToolStripMenuItem_CheckStateChanged(object sender, } } + private void SplitSentencesMenuItem_CheckStateChanged(object sender, EventArgs e) + { + var theNllbEncConverter = TheTranslators.FirstOrDefault(t => t.Configurator?.ConfiguratorDisplayName == NllbEncConverterDisplayName); + if (theNllbEncConverter == null) + return; // shouldn't be possible, but... + + var polarity = (SentenceSplittingMenuItem.Checked) ? "ON" : "OFF"; + theNllbEncConverter.Convert(NllbEncConverterSplitSentencesPrefix + polarity); + ProcessRetranslate(nllbOnly: true); + } + private void Reload() { System.Diagnostics.Debug.Assert(_model != null); @@ -1111,19 +1127,7 @@ private void TextBoxTargetBackTranslation_PreviewKeyDown(object sender, PreviewK _queryAboutF5Meaning = false; } - // I don't think I wanted to do this. This just means that if we originally processed the existing - // text (in Ptx), then it would just shift to the other one, which isn't what we probably want - // to do. - // _model.TargetData = null; // so it'll be reinitialized - _model.TargetsPossible.Clear(); - - // also remove any existing translations for the current sourceData - var sourceToTranslate = _model.SourceToTranslate; - if (!string.IsNullOrEmpty(sourceToTranslate)) - { - _mapOfRecentTranslations.Values.ToList().ForEach(m => m.Remove(sourceToTranslate)); - } - Reload(); + ProcessRetranslate(nllbOnly: false); return; } @@ -1140,40 +1144,70 @@ private void TextBoxTargetBackTranslation_PreviewKeyDown(object sender, PreviewK } } - private void TextBoxPossibleTargetTranslation_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e) - { - if (e.KeyData == (Keys.Control | Keys.Down)) - CopySelectedTextToTargetTranslationTextBox(sender); - } - - private void TextBoxPossibleTargetTranslation_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) - { - if (e.Button == MouseButtons.Right) - CopySelectedTextToTargetTranslationTextBox(sender); - } - - private void CopySelectedTextToTargetTranslationTextBox(object sender) - { - // if the user has text selected in one of the possible translation text boxes and an insertion point in the target Translation text box - // AND if they press Ctrl+Down arrow, then copy that text down to the insertion point - var textBox = sender as TextBox; - var cursorPosition = textBoxTargetBackTranslation.SelectionStart; - var textToInsert = textBox.SelectedText; - var textToReplace = textBoxTargetBackTranslation.SelectedText; - if (!string.IsNullOrEmpty(textToInsert) && (cursorPosition >= 0)) - { - if (!String.IsNullOrEmpty(textToReplace)) - textBoxTargetBackTranslation.SelectedText = String.Empty; - - cursorPosition = textBoxTargetBackTranslation.SelectionStart; - textToReplace = textBoxTargetBackTranslation.Text; - textBoxTargetBackTranslation.Text = textBoxTargetBackTranslation.Text.Insert(cursorPosition, textToInsert); - textBoxTargetBackTranslation.SelectionStart = cursorPosition + textToInsert.Length; - textBoxTargetBackTranslation.Focus(); - } - } - - private static bool _ignoreChange; + private void ProcessRetranslate(bool nllbOnly) + { + // I don't think I wanted to do this. This just means that if we originally processed the existing + // text (in Ptx), then it would just shift to the other one, which isn't what we probably want + // to do. + // _model.TargetData = null; // so it'll be reinitialized + // UPDATE: this is what we want to do in Word. Otherwise, if there's only one translator, we'll never + // see the update. + if (!_model.DisplayExistingTargetTranslation && (TheTranslators.Count == 1)) + _model.TargetData = String.Empty; + + var targetsToClear = _model.TargetsPossible; + if (nllbOnly) + { + var nllbTranslatorNames = TheTranslators.Where(t => t.Configurator?.ConfiguratorDisplayName == NllbEncConverterDisplayName).Select(t => t.Name).ToHashSet(); + targetsToClear = targetsToClear.Where(tp => nllbTranslatorNames.Contains(tp.TranslatorName)) + .ToList(); + } + + targetsToClear.Clear(); + + // also remove any existing translations for the current sourceData, so it knows it needs to retranslate + var sourceToTranslate = _model.SourceToTranslate; + if (!string.IsNullOrEmpty(sourceToTranslate)) + { + _mapOfRecentTranslations.Values.ToList().ForEach(m => m.Remove(sourceToTranslate)); + } + Reload(); + } + + private void TextBoxPossibleTargetTranslation_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e) + { + if (e.KeyData == (Keys.Control | Keys.Down)) + CopySelectedTextToTargetTranslationTextBox(sender); + } + + private void TextBoxPossibleTargetTranslation_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + CopySelectedTextToTargetTranslationTextBox(sender); + } + + private void CopySelectedTextToTargetTranslationTextBox(object sender) + { + // if the user has text selected in one of the possible translation text boxes and an insertion point in the target Translation text box + // AND if they press Ctrl+Down arrow, then copy that text down to the insertion point + var textBox = sender as TextBox; + var cursorPosition = textBoxTargetBackTranslation.SelectionStart; + var textToInsert = textBox.SelectedText; + var textToReplace = textBoxTargetBackTranslation.SelectedText; + if (!string.IsNullOrEmpty(textToInsert) && (cursorPosition >= 0)) + { + if (!String.IsNullOrEmpty(textToReplace)) + textBoxTargetBackTranslation.SelectedText = String.Empty; + + cursorPosition = textBoxTargetBackTranslation.SelectionStart; + textToReplace = textBoxTargetBackTranslation.Text; + textBoxTargetBackTranslation.Text = textBoxTargetBackTranslation.Text.Insert(cursorPosition, textToInsert); + textBoxTargetBackTranslation.SelectionStart = cursorPosition + textToInsert.Length; + textBoxTargetBackTranslation.Focus(); + } + } + + private static bool _ignoreChange; private void DisplayRighttoleftToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { _ignoreChange = true; diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs index d902796a..eae36ea0 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.designer.cs @@ -55,6 +55,7 @@ private void InitializeComponent() this.buttonFillExistingTargetText = new System.Windows.Forms.Button(); this.labelForPossibleTargetTranslation1 = new System.Windows.Forms.Label(); this.textBoxPossibleTargetTranslation1 = new System.Windows.Forms.TextBox(); + this.contextMenuHideDefault = new System.Windows.Forms.ContextMenu(); this.buttonFillTargetTextOption1 = new System.Windows.Forms.Button(); this.labelForPossibleTargetTranslation2 = new System.Windows.Forms.Label(); this.textBoxPossibleTargetTranslation2 = new System.Windows.Forms.TextBox(); @@ -81,8 +82,8 @@ private void InitializeComponent() this.toolTip = new System.Windows.Forms.ToolTip(this.components); this.buttonPinToTop = new System.Windows.Forms.Button(); this.fontDialog = new System.Windows.Forms.FontDialog(); - this.contextMenuHideDefault = new System.Windows.Forms.ContextMenu(); - this.menuStrip.SuspendLayout(); + this.SentenceSplittingMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.menuStrip.SuspendLayout(); this.tableLayoutPanel.SuspendLayout(); this.substitutionContextMenu.SuspendLayout(); this.SuspendLayout(); @@ -95,7 +96,7 @@ private void InitializeComponent() this.toolStripTextBoxStatus}); this.menuStrip.Location = new System.Drawing.Point(0, 0); this.menuStrip.Name = "menuStrip"; - this.menuStrip.Size = new System.Drawing.Size(571, 27); + this.menuStrip.Size = new System.Drawing.Size(691, 27); this.menuStrip.TabIndex = 0; this.menuStrip.Text = "menuStrip1"; // @@ -109,7 +110,8 @@ private void InitializeComponent() this.autoSaveToolStripMenuItem, this.hideColumn1LabelsToolStripMenuItem, this.hideCurrentTargetTextToolStripMenuItem, - this.hideSourceTextToolStripMenuItem}); + this.hideSourceTextToolStripMenuItem, + this.SentenceSplittingMenuItem}); this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 23); this.settingsToolStripMenuItem.Text = "&Settings"; @@ -118,15 +120,16 @@ private void InitializeComponent() // removeEncConverterToolStripMenuItem // this.removeEncConverterToolStripMenuItem.Name = "removeEncConverterToolStripMenuItem"; - this.removeEncConverterToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.removeEncConverterToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.removeEncConverterToolStripMenuItem.Text = "Edit, Remove or Reorder &Translators/EncConverters"; - this.removeEncConverterToolStripMenuItem.ToolTipText = "Click to bring up a dialog to edit, remove or reorder the Translators/EncConverters."; + this.removeEncConverterToolStripMenuItem.ToolTipText = "Click to bring up a dialog to edit, remove or reorder the Translators/EncConverte" + + "rs."; this.removeEncConverterToolStripMenuItem.Click += new System.EventHandler(this.ChangeEncConverterToolStripMenuItem_Click); // // addEncConverterToolStripMenuItem // this.addEncConverterToolStripMenuItem.Name = "addEncConverterToolStripMenuItem"; - this.addEncConverterToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.addEncConverterToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.addEncConverterToolStripMenuItem.Text = "&Add Translator/EncConverter"; this.addEncConverterToolStripMenuItem.ToolTipText = "Click to add an additional Translator/EncConverter to give multiple options for t" + "he translated draft of the source text (e.g. DeepL Translator)"; @@ -138,7 +141,7 @@ private void InitializeComponent() this.sourceTextToolStripMenuItem, this.targetTextToolStripMenuItem}); this.fontsToolStripMenuItem.Name = "fontsToolStripMenuItem"; - this.fontsToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.fontsToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.fontsToolStripMenuItem.Text = "&Fonts"; // // sourceTextToolStripMenuItem @@ -161,7 +164,7 @@ private void InitializeComponent() this.sourceRightToLeftToolStripMenuItem, this.targetRightToLeftToolStripMenuItem}); this.displayRighttoleftToolStripMenuItem.Name = "displayRighttoleftToolStripMenuItem"; - this.displayRighttoleftToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.displayRighttoleftToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.displayRighttoleftToolStripMenuItem.Text = "&Display right-to-left"; this.displayRighttoleftToolStripMenuItem.DropDownOpening += new System.EventHandler(this.DisplayRighttoleftToolStripMenuItem_DropDownOpening); // @@ -187,7 +190,7 @@ private void InitializeComponent() this.autoSaveToolStripMenuItem.CheckOnClick = true; this.autoSaveToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.autoSaveToolStripMenuItem.Name = "autoSaveToolStripMenuItem"; - this.autoSaveToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.autoSaveToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.autoSaveToolStripMenuItem.Text = "&Auto-Save"; this.autoSaveToolStripMenuItem.ToolTipText = "If this is checked, then the translated text changes will be saved when clicking " + "the \'Next\' button"; @@ -196,7 +199,7 @@ private void InitializeComponent() // this.hideColumn1LabelsToolStripMenuItem.CheckOnClick = true; this.hideColumn1LabelsToolStripMenuItem.Name = "hideColumn1LabelsToolStripMenuItem"; - this.hideColumn1LabelsToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.hideColumn1LabelsToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.hideColumn1LabelsToolStripMenuItem.Text = "&Hide column1 labels"; this.hideColumn1LabelsToolStripMenuItem.ToolTipText = "Check this menu item to hide the column 1 labels to make more room for the transl" + "ated text options"; @@ -206,7 +209,7 @@ private void InitializeComponent() // this.hideCurrentTargetTextToolStripMenuItem.CheckOnClick = true; this.hideCurrentTargetTextToolStripMenuItem.Name = "hideCurrentTargetTextToolStripMenuItem"; - this.hideCurrentTargetTextToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.hideCurrentTargetTextToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.hideCurrentTargetTextToolStripMenuItem.Text = "Hide &Current Target Text"; this.hideCurrentTargetTextToolStripMenuItem.ToolTipText = "Check this menu item to hide the Current Target Text row (e.g. to get more screen" + " real estate)"; @@ -216,7 +219,7 @@ private void InitializeComponent() // this.hideSourceTextToolStripMenuItem.CheckOnClick = true; this.hideSourceTextToolStripMenuItem.Name = "hideSourceTextToolStripMenuItem"; - this.hideSourceTextToolStripMenuItem.Size = new System.Drawing.Size(315, 22); + this.hideSourceTextToolStripMenuItem.Size = new System.Drawing.Size(341, 22); this.hideSourceTextToolStripMenuItem.Text = "Hide &Source Text"; this.hideSourceTextToolStripMenuItem.ToolTipText = "Check this menu item to hide the Source Text row (e.g. to get more screen real es" + "tate)"; @@ -226,6 +229,7 @@ private void InitializeComponent() // this.toolStripTextBoxStatus.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; this.toolStripTextBoxStatus.BackColor = System.Drawing.SystemColors.ButtonShadow; + this.toolStripTextBoxStatus.Font = new System.Drawing.Font("Segoe UI", 9F); this.toolStripTextBoxStatus.Name = "toolStripTextBoxStatus"; this.toolStripTextBoxStatus.ReadOnly = true; this.toolStripTextBoxStatus.Size = new System.Drawing.Size(500, 23); @@ -237,14 +241,14 @@ private void InitializeComponent() this.tableLayoutPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - // It's possible that if this control is edited, the designer will remove these two lines. - // if these two lines are re-added, then the tableLayoutPanel will lose 2 pixels of height - // for every verse we process. Removing them caused that to stop (and it still allows resizing) - // if the form it's in is resized. - // Restore and keep this note here too if it is removed, so the next person won't spend hours trying to figure this out too :-) - // this.tableLayoutPanel.AutoSize = true; - // this.tableLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel.ColumnCount = 7; + // It's possible that if this control is edited, the designer will remove these two lines. + // if these two lines are re-added, then the tableLayoutPanel will lose 2 pixels of height + // for every verse we process. Removing them caused that to stop (and it still allows resizing) + // if the form it's in is resized. + // Restore and keep this note here too if it is removed, so the next person won't spend hours trying to figure this out too :-) + // this.tableLayoutPanel.AutoSize = true; + // this.tableLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel.ColumnCount = 7; this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 108F)); this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); @@ -312,14 +316,14 @@ private void InitializeComponent() this.textBoxSourceData.Name = "textBoxSourceData"; this.textBoxSourceData.ReadOnly = true; this.textBoxSourceData.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBoxSourceData.Size = new System.Drawing.Size(577, 42); + this.textBoxSourceData.Size = new System.Drawing.Size(577, 41); this.textBoxSourceData.TabIndex = 11; // // labelForExistingTargetData // this.labelForExistingTargetData.Anchor = System.Windows.Forms.AnchorStyles.Right; this.labelForExistingTargetData.AutoSize = true; - this.labelForExistingTargetData.Location = new System.Drawing.Point(13, 75); + this.labelForExistingTargetData.Location = new System.Drawing.Point(13, 74); this.labelForExistingTargetData.Name = "labelForExistingTargetData"; this.labelForExistingTargetData.Size = new System.Drawing.Size(102, 13); this.labelForExistingTargetData.TabIndex = 9; @@ -330,18 +334,18 @@ private void InitializeComponent() this.textBoxTargetTextExisting.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.tableLayoutPanel.SetColumnSpan(this.textBoxTargetTextExisting, 5); this.textBoxTargetTextExisting.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBoxTargetTextExisting.Location = new System.Drawing.Point(121, 61); + this.textBoxTargetTextExisting.Location = new System.Drawing.Point(121, 60); this.textBoxTargetTextExisting.Multiline = true; this.textBoxTargetTextExisting.Name = "textBoxTargetTextExisting"; this.textBoxTargetTextExisting.ReadOnly = true; this.textBoxTargetTextExisting.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBoxTargetTextExisting.Size = new System.Drawing.Size(548, 42); + this.textBoxTargetTextExisting.Size = new System.Drawing.Size(548, 41); this.textBoxTargetTextExisting.TabIndex = 11; // // buttonFillExistingTargetText // this.buttonFillExistingTargetText.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; - this.buttonFillExistingTargetText.Location = new System.Drawing.Point(675, 61); + this.buttonFillExistingTargetText.Location = new System.Drawing.Point(675, 60); this.buttonFillExistingTargetText.Name = "buttonFillExistingTargetText"; this.buttonFillExistingTargetText.Size = new System.Drawing.Size(23, 23); this.buttonFillExistingTargetText.TabIndex = 8; @@ -353,7 +357,7 @@ private void InitializeComponent() // this.labelForPossibleTargetTranslation1.Anchor = System.Windows.Forms.AnchorStyles.Right; this.labelForPossibleTargetTranslation1.AutoSize = true; - this.labelForPossibleTargetTranslation1.Location = new System.Drawing.Point(49, 122); + this.labelForPossibleTargetTranslation1.Location = new System.Drawing.Point(49, 119); this.labelForPossibleTargetTranslation1.Margin = new System.Windows.Forms.Padding(3); this.labelForPossibleTargetTranslation1.Name = "labelForPossibleTargetTranslation1"; this.labelForPossibleTargetTranslation1.Padding = new System.Windows.Forms.Padding(0, 3, 0, 0); @@ -365,22 +369,23 @@ private void InitializeComponent() // this.textBoxPossibleTargetTranslation1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.tableLayoutPanel.SetColumnSpan(this.textBoxPossibleTargetTranslation1, 5); + this.textBoxPossibleTargetTranslation1.ContextMenu = this.contextMenuHideDefault; this.textBoxPossibleTargetTranslation1.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBoxPossibleTargetTranslation1.Location = new System.Drawing.Point(121, 109); + this.textBoxPossibleTargetTranslation1.Location = new System.Drawing.Point(121, 107); this.textBoxPossibleTargetTranslation1.Multiline = true; this.textBoxPossibleTargetTranslation1.Name = "textBoxPossibleTargetTranslation1"; this.textBoxPossibleTargetTranslation1.ReadOnly = true; this.textBoxPossibleTargetTranslation1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBoxPossibleTargetTranslation1.Size = new System.Drawing.Size(548, 42); + this.textBoxPossibleTargetTranslation1.Size = new System.Drawing.Size(548, 41); this.textBoxPossibleTargetTranslation1.TabIndex = 11; - this.textBoxPossibleTargetTranslation1.ContextMenu = contextMenuHideDefault; - this.textBoxPossibleTargetTranslation1.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; - this.textBoxPossibleTargetTranslation1.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; + this.textBoxPossibleTargetTranslation1.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation1.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation1.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; // // buttonFillTargetTextOption1 // this.buttonFillTargetTextOption1.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; - this.buttonFillTargetTextOption1.Location = new System.Drawing.Point(675, 109); + this.buttonFillTargetTextOption1.Location = new System.Drawing.Point(675, 107); this.buttonFillTargetTextOption1.Name = "buttonFillTargetTextOption1"; this.buttonFillTargetTextOption1.Size = new System.Drawing.Size(23, 23); this.buttonFillTargetTextOption1.TabIndex = 8; @@ -393,7 +398,7 @@ private void InitializeComponent() // this.labelForPossibleTargetTranslation2.Anchor = System.Windows.Forms.AnchorStyles.Right; this.labelForPossibleTargetTranslation2.AutoSize = true; - this.labelForPossibleTargetTranslation2.Location = new System.Drawing.Point(49, 170); + this.labelForPossibleTargetTranslation2.Location = new System.Drawing.Point(49, 166); this.labelForPossibleTargetTranslation2.Margin = new System.Windows.Forms.Padding(3); this.labelForPossibleTargetTranslation2.Name = "labelForPossibleTargetTranslation2"; this.labelForPossibleTargetTranslation2.Padding = new System.Windows.Forms.Padding(0, 3, 0, 0); @@ -405,22 +410,23 @@ private void InitializeComponent() // this.textBoxPossibleTargetTranslation2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.tableLayoutPanel.SetColumnSpan(this.textBoxPossibleTargetTranslation2, 5); + this.textBoxPossibleTargetTranslation2.ContextMenu = this.contextMenuHideDefault; this.textBoxPossibleTargetTranslation2.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBoxPossibleTargetTranslation2.Location = new System.Drawing.Point(121, 157); + this.textBoxPossibleTargetTranslation2.Location = new System.Drawing.Point(121, 154); this.textBoxPossibleTargetTranslation2.Multiline = true; this.textBoxPossibleTargetTranslation2.Name = "textBoxPossibleTargetTranslation2"; this.textBoxPossibleTargetTranslation2.ReadOnly = true; this.textBoxPossibleTargetTranslation2.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBoxPossibleTargetTranslation2.Size = new System.Drawing.Size(548, 42); + this.textBoxPossibleTargetTranslation2.Size = new System.Drawing.Size(548, 41); this.textBoxPossibleTargetTranslation2.TabIndex = 12; - this.textBoxPossibleTargetTranslation2.ContextMenu = contextMenuHideDefault; - this.textBoxPossibleTargetTranslation2.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; - this.textBoxPossibleTargetTranslation2.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; - // - // buttonFillTargetTextOption2 - // - this.buttonFillTargetTextOption2.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; - this.buttonFillTargetTextOption2.Location = new System.Drawing.Point(675, 157); + this.textBoxPossibleTargetTranslation2.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation2.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation2.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; + // + // buttonFillTargetTextOption2 + // + this.buttonFillTargetTextOption2.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; + this.buttonFillTargetTextOption2.Location = new System.Drawing.Point(675, 154); this.buttonFillTargetTextOption2.Name = "buttonFillTargetTextOption2"; this.buttonFillTargetTextOption2.Size = new System.Drawing.Size(23, 23); this.buttonFillTargetTextOption2.TabIndex = 8; @@ -432,7 +438,7 @@ private void InitializeComponent() // this.labelForPossibleTargetTranslation3.Anchor = System.Windows.Forms.AnchorStyles.Right; this.labelForPossibleTargetTranslation3.AutoSize = true; - this.labelForPossibleTargetTranslation3.Location = new System.Drawing.Point(49, 218); + this.labelForPossibleTargetTranslation3.Location = new System.Drawing.Point(49, 213); this.labelForPossibleTargetTranslation3.Margin = new System.Windows.Forms.Padding(3); this.labelForPossibleTargetTranslation3.Name = "labelForPossibleTargetTranslation3"; this.labelForPossibleTargetTranslation3.Padding = new System.Windows.Forms.Padding(0, 3, 0, 0); @@ -444,22 +450,23 @@ private void InitializeComponent() // this.textBoxPossibleTargetTranslation3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.tableLayoutPanel.SetColumnSpan(this.textBoxPossibleTargetTranslation3, 5); + this.textBoxPossibleTargetTranslation3.ContextMenu = this.contextMenuHideDefault; this.textBoxPossibleTargetTranslation3.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBoxPossibleTargetTranslation3.Location = new System.Drawing.Point(121, 205); + this.textBoxPossibleTargetTranslation3.Location = new System.Drawing.Point(121, 201); this.textBoxPossibleTargetTranslation3.Multiline = true; this.textBoxPossibleTargetTranslation3.Name = "textBoxPossibleTargetTranslation3"; this.textBoxPossibleTargetTranslation3.ReadOnly = true; this.textBoxPossibleTargetTranslation3.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBoxPossibleTargetTranslation3.Size = new System.Drawing.Size(548, 42); + this.textBoxPossibleTargetTranslation3.Size = new System.Drawing.Size(548, 41); this.textBoxPossibleTargetTranslation3.TabIndex = 13; - this.textBoxPossibleTargetTranslation3.ContextMenu = contextMenuHideDefault; - this.textBoxPossibleTargetTranslation3.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; - this.textBoxPossibleTargetTranslation3.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; - // - // buttonFillTargetTextOption3 - // - this.buttonFillTargetTextOption3.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; - this.buttonFillTargetTextOption3.Location = new System.Drawing.Point(675, 205); + this.textBoxPossibleTargetTranslation3.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation3.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation3.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; + // + // buttonFillTargetTextOption3 + // + this.buttonFillTargetTextOption3.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; + this.buttonFillTargetTextOption3.Location = new System.Drawing.Point(675, 201); this.buttonFillTargetTextOption3.Name = "buttonFillTargetTextOption3"; this.buttonFillTargetTextOption3.Size = new System.Drawing.Size(23, 23); this.buttonFillTargetTextOption3.TabIndex = 8; @@ -471,7 +478,7 @@ private void InitializeComponent() // this.labelForPossibleTargetTranslation4.Anchor = System.Windows.Forms.AnchorStyles.Right; this.labelForPossibleTargetTranslation4.AutoSize = true; - this.labelForPossibleTargetTranslation4.Location = new System.Drawing.Point(49, 266); + this.labelForPossibleTargetTranslation4.Location = new System.Drawing.Point(49, 260); this.labelForPossibleTargetTranslation4.Margin = new System.Windows.Forms.Padding(3); this.labelForPossibleTargetTranslation4.Name = "labelForPossibleTargetTranslation4"; this.labelForPossibleTargetTranslation4.Padding = new System.Windows.Forms.Padding(0, 3, 0, 0); @@ -483,22 +490,23 @@ private void InitializeComponent() // this.textBoxPossibleTargetTranslation4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.tableLayoutPanel.SetColumnSpan(this.textBoxPossibleTargetTranslation4, 5); + this.textBoxPossibleTargetTranslation4.ContextMenu = this.contextMenuHideDefault; this.textBoxPossibleTargetTranslation4.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBoxPossibleTargetTranslation4.Location = new System.Drawing.Point(121, 253); + this.textBoxPossibleTargetTranslation4.Location = new System.Drawing.Point(121, 248); this.textBoxPossibleTargetTranslation4.Multiline = true; this.textBoxPossibleTargetTranslation4.Name = "textBoxPossibleTargetTranslation4"; this.textBoxPossibleTargetTranslation4.ReadOnly = true; this.textBoxPossibleTargetTranslation4.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBoxPossibleTargetTranslation4.Size = new System.Drawing.Size(548, 42); + this.textBoxPossibleTargetTranslation4.Size = new System.Drawing.Size(548, 41); this.textBoxPossibleTargetTranslation4.TabIndex = 14; - this.textBoxPossibleTargetTranslation4.ContextMenu = contextMenuHideDefault; - this.textBoxPossibleTargetTranslation4.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; - this.textBoxPossibleTargetTranslation4.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; - // - // buttonFillTargetTextOption4 - // - this.buttonFillTargetTextOption4.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; - this.buttonFillTargetTextOption4.Location = new System.Drawing.Point(675, 253); + this.textBoxPossibleTargetTranslation4.ContextMenu = contextMenuHideDefault; + this.textBoxPossibleTargetTranslation4.PreviewKeyDown += TextBoxPossibleTargetTranslation_PreviewKeyDown; + this.textBoxPossibleTargetTranslation4.MouseUp += TextBoxPossibleTargetTranslation_MouseUp; + // + // buttonFillTargetTextOption4 + // + this.buttonFillTargetTextOption4.Image = global::BackTranslationHelper.Properties.Resources.FillDownHS; + this.buttonFillTargetTextOption4.Location = new System.Drawing.Point(675, 248); this.buttonFillTargetTextOption4.Name = "buttonFillTargetTextOption4"; this.buttonFillTargetTextOption4.Size = new System.Drawing.Size(23, 23); this.buttonFillTargetTextOption4.TabIndex = 9; @@ -510,7 +518,7 @@ private void InitializeComponent() // this.labelForTargetTranslation.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.labelForTargetTranslation.AutoSize = true; - this.labelForTargetTranslation.Location = new System.Drawing.Point(19, 301); + this.labelForTargetTranslation.Location = new System.Drawing.Point(19, 295); this.labelForTargetTranslation.Margin = new System.Windows.Forms.Padding(3); this.labelForTargetTranslation.Name = "labelForTargetTranslation"; this.labelForTargetTranslation.Padding = new System.Windows.Forms.Padding(0, 3, 0, 0); @@ -522,11 +530,11 @@ private void InitializeComponent() // this.tableLayoutPanel.SetColumnSpan(this.textBoxTargetBackTranslation, 6); this.textBoxTargetBackTranslation.Dock = System.Windows.Forms.DockStyle.Fill; - this.textBoxTargetBackTranslation.Location = new System.Drawing.Point(121, 301); + this.textBoxTargetBackTranslation.Location = new System.Drawing.Point(121, 295); this.textBoxTargetBackTranslation.Multiline = true; this.textBoxTargetBackTranslation.Name = "textBoxTargetBackTranslation"; this.textBoxTargetBackTranslation.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBoxTargetBackTranslation.Size = new System.Drawing.Size(577, 42); + this.textBoxTargetBackTranslation.Size = new System.Drawing.Size(577, 41); this.textBoxTargetBackTranslation.TabIndex = 1; this.textBoxTargetBackTranslation.Enter += new System.EventHandler(this.TextBoxTargetBackTranslation_Enter); this.textBoxTargetBackTranslation.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.TextBoxTargetBackTranslation_PreviewKeyDown); @@ -674,14 +682,21 @@ private void InitializeComponent() // this.fontDialog.Font = new System.Drawing.Font("Arial Unicode MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.fontDialog.ShowColor = true; - // - // contextMenuHideDefault - // - this.contextMenuHideDefault.Name = "contextMenuHideDefault"; - // - // BackTranslationHelperCtrl - // - this.AutoSize = true; + // + // sentenceSplittingToolStripMenuItem + // + this.SentenceSplittingMenuItem.CheckOnClick = true; + this.SentenceSplittingMenuItem.Name = "sentenceSplittingToolStripMenuItem"; + this.SentenceSplittingMenuItem.Size = new System.Drawing.Size(341, 22); + this.SentenceSplittingMenuItem.Text = "Sentence S&plitting"; + this.SentenceSplittingMenuItem.ToolTipText = "Check this menu to enable sentence splitting for the NLLB Translator (Check to tu" + + "rn on processing the text in smaller sentence chunks. Use if the NLLB Translator " + + "leaves parts of the translation out because the text to translate is too long)"; + this.SentenceSplittingMenuItem.CheckStateChanged += new System.EventHandler(this.SplitSentencesMenuItem_CheckStateChanged); + // + // BackTranslationHelperCtrl + // + this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.buttonPinToTop); this.Controls.Add(this.tableLayoutPanel); @@ -698,9 +713,9 @@ private void InitializeComponent() } - #endregion + #endregion - private System.Windows.Forms.MenuStrip menuStrip; + private System.Windows.Forms.MenuStrip menuStrip; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; private System.Windows.Forms.TextBox textBoxTargetBackTranslation; private System.Windows.Forms.Button buttonWriteTextToTarget; @@ -749,6 +764,7 @@ private void InitializeComponent() private System.Windows.Forms.Label labelForPossibleTargetTranslation2; private System.Windows.Forms.Label labelForPossibleTargetTranslation3; private System.Windows.Forms.Label labelForPossibleTargetTranslation4; - private System.Windows.Forms.ContextMenu contextMenuHideDefault; - } + private System.Windows.Forms.ContextMenu contextMenuHideDefault; + public System.Windows.Forms.ToolStripMenuItem SentenceSplittingMenuItem; + } } diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.resx b/src/BackTranslationHelper/BackTranslationHelperCtrl.resx index 609543ec..def44b45 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.resx +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.resx @@ -118,18 +118,18 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 205, 17 + + 17, 17 - 125, 17 + 313, 17 - 321, 20 + 512, 17 - 213, 20 - - - 511, 20 + 403, 17 \ No newline at end of file From abf1c385f17647b53da49e9f45be353d0c4b2ae6 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Tue, 14 Nov 2023 08:11:05 -0600 Subject: [PATCH 081/113] =?UTF-8?q?change=20the=20NLLB=20server=20to=20use?= =?UTF-8?q?=20a=20=E2=80=9Cproduction=20server=E2=80=9C=20to=20get=20rid?= =?UTF-8?q?=20of=20the=20=E2=80=98development=20server=E2=80=98=20warning.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EcTranslators/NllbTranslator/Docker/Dockerfile | 1 + src/EcTranslators/NllbTranslator/Docker/server.py | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/EcTranslators/NllbTranslator/Docker/Dockerfile b/src/EcTranslators/NllbTranslator/Docker/Dockerfile index 7ced9019..9a28709d 100644 --- a/src/EcTranslators/NllbTranslator/Docker/Dockerfile +++ b/src/EcTranslators/NllbTranslator/Docker/Dockerfile @@ -13,6 +13,7 @@ COPY import_model.py . RUN python import_model.py RUN pip install flask +RUN pip install gevent COPY . . diff --git a/src/EcTranslators/NllbTranslator/Docker/server.py b/src/EcTranslators/NllbTranslator/Docker/server.py index 318807b0..02571206 100644 --- a/src/EcTranslators/NllbTranslator/Docker/server.py +++ b/src/EcTranslators/NllbTranslator/Docker/server.py @@ -1,5 +1,6 @@ from flask import Flask, render_template, request, jsonify from settings import MODEL_NAME, PORT, API_KEY +from gevent.pywsgi import WSGIServer app = Flask(__name__) @@ -54,4 +55,8 @@ def translate_text(): return jsonify({'error': str(e)}), 500 if __name__ == '__main__': - app.run(host="0.0.0.0", port=PORT, debug=True) + # Debug/Development: + # app.run(host="0.0.0.0", port=PORT, debug=True) + # Production: + http_server = WSGIServer(('', PORT), app) + http_server.serve_forever() \ No newline at end of file From 781235caaf1ab5acc305ba18ef6bbece512d2c79 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 22 Nov 2023 13:28:41 -0600 Subject: [PATCH 082/113] use a flag so that we don't re-initialize an ICU Transliterator for each call to Convert. And fixed a bug where we couldn't edit an existing custom transliterator. --- src/IcuEC/IcuTranslitAutoConfigDialog.cs | 151 +++++++++------------- src/IcuEC/IcuTranslitEncConverter.cs | 47 +++---- src/IcuEC/Properties/Settings.Designer.cs | 20 +-- src/IcuEC/Properties/Settings.settings | 6 +- src/IcuEC/app.config | 34 ++--- 5 files changed, 114 insertions(+), 144 deletions(-) diff --git a/src/IcuEC/IcuTranslitAutoConfigDialog.cs b/src/IcuEC/IcuTranslitAutoConfigDialog.cs index 43844f9f..52e58c59 100755 --- a/src/IcuEC/IcuTranslitAutoConfigDialog.cs +++ b/src/IcuEC/IcuTranslitAutoConfigDialog.cs @@ -11,6 +11,7 @@ using System.IO; using ECInterfaces; using IcuEC.Properties; +using System.Linq; // for IEncConverter @@ -71,7 +72,7 @@ static extern string CppGetDisplayName_Linux( private ComboBox comboBoxPreviousCustomTransliterators; private Label label1; private Button buttonDeletePreviousCustomTransliterators; // set at the end of Initialize (to block certain events until we're ready for them) - private List lstTranslitIDs; + private Dictionary mapTransliteratorIdsToFriendlyNames; public IcuTranslitAutoConfigDialog( IEncConverters aECs, @@ -86,7 +87,6 @@ public IcuTranslitAutoConfigDialog( { Util.DebugWriteLine(this, "BEGIN"); InitializeComponent(); - fillListBox(); Util.DebugWriteLine(this, "Initialized component."); base.Initialize( aECs, @@ -101,20 +101,29 @@ public IcuTranslitAutoConfigDialog( bIsInRepository); Util.DebugWriteLine(this, "Initialized base."); - // if we're editing, then set the Converter Spec and say it's unmodified - if (m_bEditMode) + mapTransliteratorIdsToFriendlyNames = GetSupportedTransliterators(); + FillListBox(mapTransliteratorIdsToFriendlyNames); + + // if we're editing, then set the Converter Spec and say it's unmodified + if (m_bEditMode) { Util.DebugWriteLine(this, "Edit mode"); System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(ConverterIdentifier)); - //listBoxTranslitName.SelectedValue = ConverterIdentifier; - for (int i = 0; i < lstTranslitIDs.Count; i++) - { - if (lstTranslitIDs[i] == ConverterIdentifier) - { - listBoxTranslitName.SelectedIndex = i; - break; - } - } + + // first see if the converter identifier is one of the values in the text box + var value = mapTransliteratorIdsToFriendlyNames.FirstOrDefault(kvp => kvp.Key == ConverterIdentifier || kvp.Value == ConverterIdentifier); + if (!value.Equals(default(KeyValuePair))) + { + listBoxTranslitName.SelectedItem = value.Value; + } + else + { + // it's a custom transliterator, so set the other radio box and load the text box as is + textBoxCustomTransliterator.Text = ConverterIdentifier; + radioButtonCustom.Checked = true; + radioButtonCustom.PerformClick(); + } + IsModified = false; } @@ -127,7 +136,21 @@ public IcuTranslitAutoConfigDialog( Util.DebugWriteLine(this, "END"); } - public IcuTranslitAutoConfigDialog( + private Dictionary GetSupportedTransliterators() + { + var count = CppConverterNameList_start(); + + var map = new Dictionary(); + for (int i = 0; i < count; i++) + { + var translitId = CppConverterNameList_next(); + var translitName = CppGetDisplayName(translitId); + map[translitId] = translitName; + } + return map; + } + + public IcuTranslitAutoConfigDialog( IEncConverters aECs, string strFriendlyName, string strConverterIdentifier, @@ -135,7 +158,6 @@ public IcuTranslitAutoConfigDialog( string strTestData) { InitializeComponent(); - fillListBox(); base.Initialize( aECs, strFriendlyName, @@ -143,11 +165,14 @@ public IcuTranslitAutoConfigDialog( eConversionType, strTestData); m_bInitialized = true; - } - // This code was NOT generated! - // So feel free to modify it as needed. - private void InitializeComponent() + mapTransliteratorIdsToFriendlyNames = GetSupportedTransliterators(); + FillListBox(mapTransliteratorIdsToFriendlyNames); + } + + // This code was NOT generated! + // So feel free to modify it as needed. + private void InitializeComponent() { this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); this.listBoxTranslitName = new System.Windows.Forms.ListBox(); @@ -219,6 +244,7 @@ private void InitializeComponent() this.listBoxTranslitName.Name = "listBoxTranslitName"; this.listBoxTranslitName.Size = new System.Drawing.Size(370, 212); this.listBoxTranslitName.TabIndex = 1; + this.listBoxTranslitName.Sorted = true; this.listBoxTranslitName.SelectedIndexChanged += new System.EventHandler(this.listBoxTranslitName_SelectedIndexChanged); // // radioButtonBuiltIn @@ -244,7 +270,7 @@ private void InitializeComponent() this.radioButtonCustom.TabStop = true; this.radioButtonCustom.Text = "&Custom transliterator"; this.radioButtonCustom.UseVisualStyleBackColor = true; - this.radioButtonCustom.Click += new System.EventHandler(this.radioButtonCustom_Click); + this.radioButtonCustom.CheckedChanged += new System.EventHandler(this.radioButtonCustom_CheckedChanged); // // textBoxCustomTransliterator // @@ -305,54 +331,13 @@ private void InitializeComponent() } - private void fillListBox() + private void FillListBox(Dictionary mapTransliteratorIdsToFriendlyNames) { - this.listBoxTranslitName.Items.Clear(); - int count = 0; - count = CppConverterNameList_start(); - - // Store the IDs in an array, and put the display names in the - // list box. - lstTranslitIDs = new List(count); - for (int i = 0; i < count; i++) - { - var translitId = CppConverterNameList_next(); - lstTranslitIDs.Add(translitId); - string translitName = CppGetDisplayName(translitId); - this.listBoxTranslitName.Items.Add(translitName); - } - - // Sort listbox and corresponding translitIDs by display name. - ListBox lb = this.listBoxTranslitName; // shorter nickname - if (lb.Items.Count > 1) - { - bool swapped; - do - { - int counter = lb.Items.Count - 1; - swapped = false; - - while (counter > 0) - { - // Compare the items - if (String.Compare(lb.Items[counter].ToString(), - lb.Items[counter - 1].ToString()) < 0) - { - // Swap the items. - object tempName = lb.Items[counter]; - lb.Items[counter] = lb.Items[counter - 1]; - lb.Items[counter - 1] = tempName; - string tempID = lstTranslitIDs[counter]; - lstTranslitIDs[counter] = lstTranslitIDs[counter - 1]; - lstTranslitIDs[counter - 1] = tempID; - swapped = true; - } - // Decrement the counter. - counter -= 1; - } - } - while ((swapped == true)); - } + // Put the display names in the list box. + foreach (var friendlyName in mapTransliteratorIdsToFriendlyNames.Values) + { + this.listBoxTranslitName.Items.Add(friendlyName); + } } protected override void SetConvTypeControls() @@ -370,7 +355,7 @@ protected override bool OnApply() // Get the converter identifier from the Setup tab controls. if (radioButtonBuiltIn.Checked && (listBoxTranslitName.SelectedIndex != -1)) - ConverterIdentifier = lstTranslitIDs[listBoxTranslitName.SelectedIndex]; + ConverterIdentifier = mapTransliteratorIdsToFriendlyNames.FirstOrDefault(kvp => kvp.Value == (string)listBoxTranslitName.SelectedItem).Key; else if (radioButtonCustom.Checked) ConverterIdentifier = textBoxCustomTransliterator.Text; @@ -399,23 +384,6 @@ protected override bool OnApply() return base.OnApply(); } -/* - protected override bool ShouldRemoveBeforeAdd - { - get { return true; } - } - - protected override bool ShouldFriendlyNameBeReadOnly - { - get { return false; } - } - - protected override bool GetFontMapping(string strFriendlyName, out string strLhsFont, out string strRhsFont) - { - return base.GetFontMapping(strFriendlyName, out strLhsFont, out strRhsFont); - } -*/ - protected override string ProgID { get { return typeof(IcuTranslitEncConverter).FullName; } @@ -457,17 +425,20 @@ private void radioButtonBuiltIn_Click(object sender, EventArgs e) textBoxCustomTransliterator.Enabled = comboBoxPreviousCustomTransliterators.Enabled = buttonDeletePreviousCustomTransliterators.Enabled = false; + IsModified = true; } - private void radioButtonCustom_Click(object sender, EventArgs e) + private void radioButtonCustom_CheckedChanged(object sender, EventArgs e) { - listBoxTranslitName.Enabled = false; + var value = radioButtonCustom.Checked; + listBoxTranslitName.Enabled = !value; textBoxCustomTransliterator.Enabled = comboBoxPreviousCustomTransliterators.Enabled = - buttonDeletePreviousCustomTransliterators.Enabled = true; - } + buttonDeletePreviousCustomTransliterators.Enabled = value; + IsModified = true; + } - private void comboBoxPreviousCustomTransliterators_SelectedIndexChanged(object sender, EventArgs e) + private void comboBoxPreviousCustomTransliterators_SelectedIndexChanged(object sender, EventArgs e) { if (!m_bInitialized) return; diff --git a/src/IcuEC/IcuTranslitEncConverter.cs b/src/IcuEC/IcuTranslitEncConverter.cs index d6cdce35..0f52b0bf 100755 --- a/src/IcuEC/IcuTranslitEncConverter.cs +++ b/src/IcuEC/IcuTranslitEncConverter.cs @@ -80,6 +80,9 @@ static extern string CppGetDisplayName_Linux( #region Member Variable Definitions public const string strDisplayName = "ICU Transliterator"; public const string strHtmlFilename = "ICU_Transliterators_Plug-in_About_box.htm"; + + public bool TransliteratorInitialized { get; set; } + #endregion Member Variable Definitions #region Initialization @@ -90,14 +93,6 @@ public IcuTranslitEncConverter() : base( { } - ///

- /// The class destructor. - ~IcuTranslitEncConverter() - { - //if( IsFileLoaded() ) - // CCUnloadTable(m_hTable); - } - public override void Initialize( string converterName, string converterSpec, @@ -120,7 +115,9 @@ public override void Initialize( if (converterSpec.Contains("Any")) m_eConversionType = conversionType = MakeUniDirectional(conversionType); - Util.DebugWriteLine(this, "END"); + TransliteratorInitialized = false; // so it has to be reinitialized in the C++ side + + Util.DebugWriteLine(this, "END"); } #endregion Initialization @@ -128,18 +125,7 @@ public override void Initialize( #region Misc helpers protected bool IsFileLoaded() { - //return (m_hTable != 0); - return false; - } - - protected void Unload() - { - //Util.DebugWriteLine(this, "BEGIN"); - //if( IsFileLoaded() ) - //{ - // CCUnloadTable(m_hTable); - // m_hTable = 0; - //} + return TransliteratorInitialized; } protected override EncodingForm DefaultUnicodeEncForm(bool bForward, bool bLHS) @@ -154,18 +140,23 @@ protected unsafe void Load(string strTranslitID) { Util.DebugWriteLine(this, "BEGIN"); - if (IsFileLoaded()) - Unload(); + if (IsFileLoaded()) + return; Util.DebugWriteLine(this, "Calling CppInitialize"); int status = 0; status = CppInitialize(strTranslitID); - if (status != 0) - { - throw new Exception("CppInitialize failed."); - } - Util.DebugWriteLine(this, "END"); + if (status != 0) + { + throw new Exception("CppInitialize failed."); + } + else + { + TransliteratorInitialized = true; + } + + Util.DebugWriteLine(this, "END"); } #endregion Misc helpers diff --git a/src/IcuEC/Properties/Settings.Designer.cs b/src/IcuEC/Properties/Settings.Designer.cs index a68e0c36..fac30a0c 100644 --- a/src/IcuEC/Properties/Settings.Designer.cs +++ b/src/IcuEC/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace IcuEC.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -25,10 +25,12 @@ public static Settings Default { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("\r\n\r\n [aeiou]->V /i\r\n [^aeiou]->C /i\r\n")] + [global::System.Configuration.DefaultSettingValueAttribute(@" + + [aeiou]->V /i + [^aeiou]->C /i + [\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD]-> +")] public global::System.Collections.Specialized.StringCollection RecentRegExpressions { get { return ((global::System.Collections.Specialized.StringCollection)(this["RecentRegExpressions"])); @@ -40,9 +42,11 @@ public static Settings Default { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("\r\n\r\n NFD; [:Nonspacing Mark:] Remove; NFC\r\n")] + [global::System.Configuration.DefaultSettingValueAttribute(@" + + NFD; [:Nonspacing Mark:] Remove; NFC + Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC +")] public global::System.Collections.Specialized.StringCollection RecentCustomTransliterators { get { return ((global::System.Collections.Specialized.StringCollection)(this["RecentCustomTransliterators"])); diff --git a/src/IcuEC/Properties/Settings.settings b/src/IcuEC/Properties/Settings.settings index f75a0e9e..2b030931 100644 --- a/src/IcuEC/Properties/Settings.settings +++ b/src/IcuEC/Properties/Settings.settings @@ -4,15 +4,17 @@ <?xml version="1.0" encoding="utf-16"?> -<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> +<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <string>[aeiou]-&gt;V /i</string> <string>[^aeiou]-&gt;C /i</string> + <string>[\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD]-&gt;</string> </ArrayOfString> <?xml version="1.0" encoding="utf-16"?> -<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> +<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <string>NFD; [:Nonspacing Mark:] Remove; NFC</string> + <string>Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC</string> </ArrayOfString> diff --git a/src/IcuEC/app.config b/src/IcuEC/app.config index 588d5cc6..3401a124 100644 --- a/src/IcuEC/app.config +++ b/src/IcuEC/app.config @@ -7,22 +7,24 @@ - - - - [aeiou]->V /i - [^aeiou]->C /i - - - - - - - NFD; [:Nonspacing Mark:] Remove; NFC - - - - + + + + [aeiou]->V /i + [^aeiou]->C /i + [\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD]-> + + + + + + + NFD; [:Nonspacing Mark:] Remove; NFC + Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC + + + + From 9a0d22aa317c1f097164e0acf8a20ec4bb727dc2 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 22 Nov 2023 14:34:54 -0600 Subject: [PATCH 083/113] ICU has a bug in it (or our C++ implementation for it, which I can't make work) that makes it so that it won't properly process certain characters in UTF-8 (see the TestICURegex.cpp for details). I added an EncConverter wrapping the .Net Regex engine. --- EncConverters 2019.sln | 1 + .../EC_40_64bit_MM/EC_40_MergeModule.wxs | 54 +- installer/EC_40_MM/EC_40_MergeModule.wxs | 54 +- .../EC/Plugins/EC 4.0.0.0 Plugin Details.xml | 7 + ...t_Regular_Expression_Plug-in_About_box.htm | 1870 +++++++++++++++++ .../colorschememapping.xml | 2 + .../filelist.xml | 12 + .../image001.jpg | Bin 0 -> 19699 bytes .../image002.jpg | Bin 0 -> 30378 bytes .../image003.jpg | Bin 0 -> 10125 bytes .../image005.jpg | Bin 0 -> 21931 bytes .../item0010.xml | 1 + .../props011.xml | 2 + .../themedata.thmx | Bin 0 -> 3104 bytes src/EncCnvtrs/AutoConfigDialog.Designer.cs | 2 +- src/EncCnvtrs/AutoConfigDialog.cs | 52 +- src/EncCnvtrs/CmpdAutoConfigDialog.cs | 3 +- src/EncCnvtrs/EncCnvtrs 2010.csproj | 11 + src/EncCnvtrs/EncConverters.cs | 3 +- .../NetRegexAutoConfigDialog.Designer.cs | 671 ++++++ src/EncCnvtrs/NetRegexAutoConfigDialog.cs | 244 +++ src/EncCnvtrs/NetRegexAutoConfigDialog.resx | 135 ++ src/EncCnvtrs/NetRegexEncConverter.cs | 195 ++ src/EncCnvtrs/NetRegexEncConverterConfig.cs | 61 + .../Properties/Resources.Designer.cs | 11 +- src/EncCnvtrs/Properties/Resources.resx | 3 + src/EncCnvtrs/Properties/Settings.Designer.cs | 19 +- src/EncCnvtrs/Properties/Settings.settings | 13 +- src/EncCnvtrs/SelectConverter.cs | 272 +-- src/EncCnvtrs/SelectConverter.resx | 23 +- src/EncCnvtrs/app.config | 18 +- src/RunTests/Main.cs | 18 + src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj | 1 + src/TestEncCnvtrs/TestIcuRegex.cs | 3 +- src/TestEncCnvtrs/TestNetRegex.cs | 76 + 35 files changed, 3672 insertions(+), 165 deletions(-) create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box.htm create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/colorschememapping.xml create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/filelist.xml create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image001.jpg create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image002.jpg create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image003.jpg create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image005.jpg create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/item0010.xml create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/props011.xml create mode 100644 redist/Help/Net_Regular_Expression_Plug-in_About_box_files/themedata.thmx create mode 100644 src/EncCnvtrs/NetRegexAutoConfigDialog.Designer.cs create mode 100644 src/EncCnvtrs/NetRegexAutoConfigDialog.cs create mode 100644 src/EncCnvtrs/NetRegexAutoConfigDialog.resx create mode 100644 src/EncCnvtrs/NetRegexEncConverter.cs create mode 100644 src/EncCnvtrs/NetRegexEncConverterConfig.cs create mode 100644 src/TestEncCnvtrs/TestNetRegex.cs diff --git a/EncConverters 2019.sln b/EncConverters 2019.sln index 4327fbd4..41dc7962 100644 --- a/EncConverters 2019.sln +++ b/EncConverters 2019.sln @@ -18,6 +18,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ECFileConverter 2010", "src ProjectSection(ProjectDependencies) = postProject {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} + {D1BAE593-A552-4F1A-8B08-5A1C27875C2F} = {D1BAE593-A552-4F1A-8B08-5A1C27875C2F} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIGuesserEC 2010", "src\AIGuesserEC\AIGuesserEC 2010.csproj", "{B718B5F3-A49A-454C-84FD-6D6F59EC7410}" diff --git a/installer/EC_40_64bit_MM/EC_40_MergeModule.wxs b/installer/EC_40_64bit_MM/EC_40_MergeModule.wxs index e1b399cf..e60dd68b 100644 --- a/installer/EC_40_64bit_MM/EC_40_MergeModule.wxs +++ b/installer/EC_40_64bit_MM/EC_40_MergeModule.wxs @@ -278,7 +278,13 @@ - + + + + + + + @@ -454,7 +460,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -490,7 +516,10 @@ - + + + + @@ -723,6 +752,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/installer/EC_40_MM/EC_40_MergeModule.wxs b/installer/EC_40_MM/EC_40_MergeModule.wxs index b3c034b6..ec9b719a 100644 --- a/installer/EC_40_MM/EC_40_MergeModule.wxs +++ b/installer/EC_40_MM/EC_40_MergeModule.wxs @@ -278,7 +278,13 @@ - + + + + + + + @@ -454,7 +460,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -490,7 +516,10 @@ - + + + + @@ -723,6 +752,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/redist/EC/Plugins/EC 4.0.0.0 Plugin Details.xml b/redist/EC/Plugins/EC 4.0.0.0 Plugin Details.xml index d637e457..cdb0952d 100755 --- a/redist/EC/Plugins/EC 4.0.0.0 Plugin Details.xml +++ b/redist/EC/Plugins/EC 4.0.0.0 Plugin Details.xml @@ -35,4 +35,11 @@ DefiningProcessType="16" ConfiguratorProgId="SilEncConverters40.CpEncConverterConfig" AssemblyReference="SilEncConverters40, Version=4.0.0.0, Culture=neutral, PublicKeyToken=f1447bae1e63f485" /> + diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box.htm b/redist/Help/Net_Regular_Expression_Plug-in_About_box.htm new file mode 100644 index 00000000..87f29ff6 --- /dev/null +++ b/redist/Help/Net_Regular_Expression_Plug-in_About_box.htm @@ -0,0 +1,1870 @@ + + + + + + + + + + +.Net Regular Expression Help + + + + + + + + + + + +
+ +

Regular Expression +Processor (.Net)

+ +

The .Net Regular Expression converter provides +applications with the ability to apply regular expression searching and text manipulation +for Unicode string data. The regular expression patterns and behavior are based +on the .Net regular expression syntax. See https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference +for more information on the syntax of .Net Regular Expressions or this website +if you want to test the syntax to prepare your regular expression http://regexstorm.net/tester. +

+ +

Setup Tab

+ +

Here is the setup tab for the .Net Regular Expression +EncConverter:

+ +

+ +

Figure 1: +.Net Regular Expression Setup Dialog [1], +[2], +[3], +[4], +[5], +[6], +[7], +[8], +[9]

+ +

 

+ +

1.      +In the Search for +box, enter the regular expression you want to use as the search rule for text +processing. These pages shows what Character Escapes, +Character Classes, +Anchors, +Grouping Constructs, +Lookaround Expressions, +Quantifiers, +Backreference +Constructs, and Alternation Constructs +are supported by the .Net regular expression engine.

+ +

2.      +Click this button to see a pop-up list of +commonly used meta-characters and operators which will be inserted into +the Search for box if selected:

+ +

+ +

Figure 2: +Commonly Used Regular Expression Tokens

+ +

 

+ + + +

3.      +In the Replace with +box, enter the string or operator (see here +for Substitution syntax) that represents the text or grouping tokens to replace +the Search for string.

+ +

4.      +This +area shows the various RegexOptions you can choose. If you hover your cursor of +one of the check boxes, a tooltip will pop up to show you the meaning of each +option. Also, see here for more information.

+ +

5.      +The Previous Searches combo box includes a few example +regular expressions and remembers any new ones you add. Note that in this +combobox, the Search for and Replace with strings will be enclosed in +“{}” in order to maintain them in the dialog’s Settings, but +you don’t use the “{}” when adding them in the Search for and Replace +with text boxes (i.e. 1 and 2 +above). The Delete button can be used to remove the selected +search item if you need to purge the list to keep it manageable (e.g. to +remove expressions you have updated to fix its behavior).

+ +

6.      This link on the Setup tab will launch your +system defined web browser and open the learn.microsoft web page that has the quick reference guide +for the .Net regular expression syntax.

+ +

7.      +If you +want the converter to be permanently added to the System Repository, then you +must click the Save in System Repository button (see below).

+ +

8.      +You can +click on the Test Area tab in order to test the converter with +some sample data.

+ +

9.      +You can +add Advanced information (encoding names, process types, etc) using the Advanced +tab.

+ +

Saving the converter in the System Repository:

+ +

By default, if you click the Apply +or OK buttons, the configured converter will +be returned to the client application as a temporary converter for temporary +use. Once the client application (e.g. FieldWorks +or Word) is closed or releases the converter, it +will no longer be available. If you want the converter to be permanently +available to client applications, then you must explicitly add it to the System Repository using the Save +in System Repository button.

+ +

When you click this button, the following dialog box will +be displayed to query for a friendly name by +which the converter will be known in client applications:

+ +

+ +

 

+ +

For the .Net Regular Expression converter, the default +name will be the Search for and Replace with elements separated by the arrow. However, +you can change it to something more descriptive if desired (e.g. Replace +English vowels with 'V').

+ +

The Advanced Tab can be +used to enter further, optional information about this converter, which is also +put into the System Repository and can be used +by various client applications. Click on this tab to display the following:

+ +

+ +

 

+ +

Though these values are not necessary for the operation of +the converter, they can be helpful to various client applications. For example, +the Clipboard EncConverter can be configured to +filter the list of displayed converters based on the Encoding +Name and/or the Transduction Type +configured here.

+ +
+ + + + diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/colorschememapping.xml b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/colorschememapping.xml new file mode 100644 index 00000000..6a0069cd --- /dev/null +++ b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/filelist.xml b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/filelist.xml new file mode 100644 index 00000000..b325c87a --- /dev/null +++ b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/filelist.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image001.jpg b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image001.jpg new file mode 100644 index 0000000000000000000000000000000000000000..02a5f9462df2462c0f3c673768a45ae2a0c5ad92 GIT binary patch literal 19699 zcmeHv1z1&Ex9EaRgCIz^0@6r_#NMd1bVv#kA|NG=;-*EU5k#az8l+oVy1Tms1nJ!S zEj;I_=fD5`?tSll@4oxq_ro_~G54BtjxpvKV~(02$B=WtRe5PSX#fQU1uz1?0puib z7r?>9#Ky$H!N$VI#l^uRptwqak552LN=8J%NPm-wfu7+83#SM-3!5PO4F=wOyn>?Q zFc|D6x3q$kguDn8CVn{y3N9`#!4(3Ut5<2nSs7Tx|EIr@^#CCjiWSN<1my;RN{9j> zL_szKbO3;Y4nlhg@Sk5Os1P)C3`{I+99-~)(yIU}3Iu|R20=$hLj<06z!N2+@hI z^GIS`Q+?dNs@R|VdASmGGK?ngTurG?M=fTjl z!P(|kQ*l1ZOUF~W3MqFlKmypL?+$HCJiOtIWz$H&T;F^zXY`v-<8Dp(JLO{3Hl+b+ zOo}c2dyhr-&mzLvTB%->P_8D;UB!HX1QMc%J}7l?Ud-k|ss}$74RegF%uL^V+9G{i zFQ!>g)PMxUZXkir=w_}quCHF*>(i^cQJlz1UQJCq{#7~sF%{<>-0}omw;A?YnQqs~ zW2}Y;hiVuEeb0xbrVVmXhB(u!GI4FOAfJNlWybT6z-o{V60m!~^XO)^z5OGJWd60R zXZH$QEFU~!aebQEv3l%ppHRyx08TrrS3Q)wMXCb{$JYMrF{6T`U>>s(VHRKUZ za57JJvBPr4S$Dqk260T%-krS>9j&V1z@LO4!5NM+RzYPtm1>LW4fMFjX=ddM=v5|r zD=2u=$J44WZE3L!QRyX9i3=y;zuEi*@5QRy_LAk~e7CH9owfnp;Z%I4*2RTr`lMg) zB)6;AhNSGN+SO%g31ey4DmCr?_`ugu-QjPXc`?%xgHLCTIqQ}sLxqymB+;Cg4wLW$ z#wUre%YDQ9PD}y~izbo4kLmTBbw8GJ&cD9DqCLXfcM?aWt$!y+@rQhhRthNnqrwA`tfLzMB~4p!VoZV5{`M_H*B-I`%h3qFTmH+BQYUmTvq(!naldwK_+Wy5ObY|rsLlMGfQPWdAuUm;e zR?D-+#?0giqExrAk-kzR3~s$fi3%Fjq-?T$vv2DQ&vKA)2U)EBPlq|Tl3Wqm;h&Bh;7Ja7E95Zk8c|y~bN-bC-}A{=^{k=hmt9 z!w5a1XA!PaNZbpJLXCnCoA>>B{9c^bdeI@O26Ag{)97|? zt;5JT`%MRvLyV}&-*P_+bET0II^%6ZyvVED9vIARw_?FHxhcR*C#kNc2ZT$J)EEn! z$o4suVqh*ScMAp@iSj@GAWe{*g!Qqgv@(G;qugKTkx1|~3hTaj_KQI~k1OO7{+=|k ze2NYG{3<|Z;O5tCn(vjK%Y}miZ{V5JaEmEDDHmHa>Z`9I_dnDuI1Dl;eGy(M%ZaZl z4-q#$R8&xkJ!RE=+0#xILt@{tc&y~seQ(<&2Pb9eBx-;6TlL!0br)NYk9t#`bnh55 zDI)uZYesBdp|^YvM{{x8gF)G;qbTO(w!OS`NmR$lN8~gjLPkxBr7cR-`S?mV#&b6r z1bYhG`P&I%nr?8nZfmG0i~CoTCJHQ0GwzfGnnK)p6Kz^gHS@GYZVoQV=A~3JQzeJZ z-ChkNC`f<29{X@w(`KZ8{4U)wlU-qZQX&8$PGoHNfn#=CYNr_U~nYsFOX=-dy(Ml8BR)FaDhoR}ZiB`D?zN}}6i>|4p>kVBt-*FQX$w{DG^0g(8gz~R z{iy!DhtphmZQV6Cz*Rex^^Kt6@p*-Sv_Q$Xc9KAN>yS$QYU`WLEqcwNo6?oWW3miR z3^eZzSJWdz5TzC`6dv=B<*$S+h%aljEJqtHL$;3Q0^=QV(Tx!L>ANnX_m|UpgdO5O z&Dl8&BvtI>$BSWbGl%*Cuj3X0z)p$JE9jsFu+TAR@c?4!zX}nXg;|>!*-6rt##=w< zObBX*al4{twftpGtfCd<9zuoMBQ!X!lig^fM|RKh`e*!d||oI30|9 zFgPPgX*kIjHA5_0IT^IN9@vcpe6`R+q(Z*kGxrvjJh2m8WTrVnSCL7|oZoTE)wL)V z;_5KnQ$Sa7D9M+I8%8N0%`p)UXz{RFFuwQPRJ|soBD*{Hu8Vn=Kv2g@Kf(6Z9Ima( z#dVF`Zm6)fP@Em4DgLcYTf8xDjK}CNOr}Eu;UBm)=e`=IxZQlyZMav&Ei53R!h_qV99h{@zeIi%v z`3a?_v<*{OI4jh!UIj&p_`kGac)U9Ib22<#r$cz%{|nYLf)kvtbq52`3)IvRcga6A zqWj>D9-x)EQ$O(`o5|=7$(7`rJ*f4N<$TzwMr*+w3y>1{U)mrNO^7>H1s9H?NC1|3 zkRJxGuS=JEgaob|JU~>*Ab}(e_fc8soZ*1yEnS)sJ8Ht1p}B)~b=o@5OlvGFVVp3@ zU|EJAe}nwST0|cqct;xp%}fdFloALLtzfE*o)OVZ_l4XDo$tMm&=fFQD+?Pt_R;X3 z7W`7!Xdf5x@@d5L*qN+1)|S=}34OO{aua7FaRBC|ZjxTtyu3!;5ARj1xwJ%#Ef~TU zE7Y(gUX=?-GvAf6@66rkdWYF@HN{VR_=d%c+5pI)Jv3s1d_GQOg$7ty8s?BTRd zxSRs-7WwY3HW%-+DaQpb8bum*OexAh!zt|X=4+koo_&j*P%eDsd}Z3Q-ZCMxf{wxJ z&1lIm)8(+Abmf%&ddeW0<)U7d(V7A3bWjD2y_%GHMmM_@ZK>k`gS9D{QJ8(4$r`~j zjM7m{Gb%`^oQx-ZB?XPi4hdMGn`-HM^E`llx`u!s(4AvJ=V7EzvS-JzkpT2G6oE#! zlX`{%T}1+_NTA*aL5%V^Fz>=MaSsV(B7r%O$8i2N^uH6C{AqZe#(@!#w_(yZ-`Uam zDaWy_pQxa!D(XaQ*R;jc$O@Y^kf=*Xt@dv*M!gaJg3I$&5im&kR0_$O)R{5te#u!A zai2Ro=elYik6469&f^*B*a=n|XVH}6TSsyfH`3+5eJM`wBw_z3Cq=ADfljOnqd277 zB^icqq`^ zbd>Iz+zS+t4Ob=e(;$bep^NgX!q6$edDw9_WGd^1Y~(AwZ@zteKg>C%Y}s`+0ZVvM zY-EcVrKfdH4^70PlMe&`MffO(q~W(k`*p2%O{~PP87X};cj938VJA;qY}8x3<69&3 zh*i)HXd6mK;|-!x*oo~4BU)5Zmn+DbCrZwT51`@MLn`Qr0v^gsPxc-RA*6FuVWclE z`%}9O)lVq%qyU{C{h^nySe6o_nE&V(`+sLBM=m*@dC*~IJIVt_{8~jO&B{TJ0;WAK z>(r?4!CibUfQ*?@w6z0k)I&X=%EL@48hbywu3ZcMTPG;mNMQ83%pvJJBp`7WJ}dBy zCDofTkQkd1kF5a40*Mdbwkf@ts4{TtqdyrEkoFUNN{$fhdOc@HM;cOftxKA4GYGP+HvLQcC8iPIlzD9_(Vo z4#y(jh+S{!@V1kqk&%yLucp#SZ6{&;mbk`A^1&rf#@u;FptLFX4j)G*nWe3;{<0U; zQ@~<-b79J~rc5Qc@Xh^HD|cE~iD7A`K(;i>^t5j(_g^!|_Or=0=yb%2q9W}m3T zC$)BdEStP>0T~K}{xJ57yBU)F_6qitqTvlrjXu?Q zO7@{|LFXq!O2EL7i9#D6e=s&nqQKnNZbx=|<)#q&>kky`eJbb^?9j7kt!IOv;ucGs zmpNPxJ<0&Jx*N37lb_to!BKDEMF#+?j>P4l=#X1t$p;g{Vx`Oks1^-J)nq5{E zT)X5)&r1ripT5S@Iuuw6yVTIXx8Jq(-TXhK#_E^U0k^U;00)nl2L2S%Vh3=peI0mk~{mV3JTWBk#(4I*Y_ zL_9N@&#k{;(}Y+(#PYo=LlmJUfP=kJ-y$c)L`B(?6I+_M=1`RoWiOE48Y47;XM1 z>05dofp?BgnJSH3ulo~_w_~ocRP1<9OQCk#r?1+pHQZdC_ z%u0=ihXWLwQ1@#$zT+~Dqu(PxvNHc`1gjA_%{#Y_Vy1C;^QYI5SE{V1PmCE zKpz{8%b#JvO(n-OleiVer66;!$x9Eh}&ff_1lUN#x4n)PQoKbW0*sV)!x`B{AMUXzq2=5Y<2m}LmoHY%5Q<==vK9ma-0jUHivah?A29ltVDcG{OQJtEZmM_C^SI5YNYx=&&s@m+oH zhwHToYdDQL$xKtfc)Aw`K}~Bnbr=}Oq!|$k2MSnB+w|CZWI1;n$(!d(8tql zJH(xCc_bAv4(ID8ZQ7Ku^Xc8=K6?!j4FzRAMsr>xQwtcL|F`v;6w6yLXM-CD+7n$HN;m@g{HIW{*+#IH-&ru`|;Z|`)gN%}kODP;? z)*2!%%8xbKui#87)e3R9^O(>@lLXXLy907_PRulgx^5CBc(1m2-0LpRYs6%A-Zmqi$-Wu_s4&=`r( z^K9K8ZpNjn@mK5pyOOx_JiQK#2WkA~)M$Pu?r-F*X~m5n>z#*DmeqYv?o>?xM^Sd48>%t+cMl+>KWy5St`2U z)RC&5sIr*bTlr_i!V^g*UdN+46k%UJI%&QQeXp?u*|cQ1IaxXS@a=VZ{M*|uaLEH= z>XO+5P#)LV)rM3&*6TL1K-H#|yTq5M7tVRJT9AYDIv1^Z0>27zm@>0hi(&LSXYS|0 zXLz#2d<3=SVkRNARyfLN6Ax$aI%F#Hhv!5`_nS)GTN33r8~r@pI`(~CcVbCR--53N z&z7OAk5tTj8#3iJIpQfb0PB%mEZ{eFXj{y)KYU4E3dAIH{D2aazqBZ+yX+S2?QhO~>gcZHwW(N>&iXovE^0nbB2@)2Z}P zI&XI6(0u9{gctX-2amN@OiQpY5^ap^#{6{d#1(W2w==S~%{k0?#Y@X%wvI$sV(yqV zO^_=#qloR%zt(At%jeajU=|Chdw4MNrTWG_#zIX9^JjEGjnc2HxF>qTv6zFGe7rd` zDGt&XcSK@3MV=eG@Rbj^XC5v$rGc-kRD(Zcu~YiNAewFF#fqv=-&G8PWyN8_kAqx` z!8$Xt2AU5j7`;WqL{Iw!DoM%;%-!sXuPT0)vu^1K&bZJK#++OqNxVq4K7372bdBHK zB8Zhk31TO@BbjeGDqE$HIWg0-LaIigyF?#s*WewWuOuv9RVqJ2Sn*`k@i31|j!X5k zev*3m=Vwrc`|li5%WC|$a2vIg7;V^KZA`N5M;ITsLk@b%{q7fqN@$zC>6$SyW2B2! zA4E(LbR?#^+E@!|S+(2T8&|A;Be+;kWj_d^hRegOW(_U^C%boJ)eKZ_gkf{o-M+B6 zp74D|^MhgpvAC&4nAb5RR_{!!+KWM2lbz!k(M(`{;_`!7gC=rFqArH{^jGIYbw;(5 z+;7!|#P`o02v3bs6Sxyp(?a$ppzT3G2T zcvV>Zwo87{E25AIkqv2G{jx&rZv8=_J$Vlwwmh=A87C`g1}jW<=9mJ2 zrJ-0;MU(W&iAt>}VXQ{30v{HvEb{l$11F~QsTHX3|F*ji(b=Pj#c|`m>s#hO3^z~X}igOHfdo)IU=f~h3Unq^Tw7*mY^bX z4{wgho%AqA@H1(Gpq$v`b9lvzOyaFjyjx&(&zDS*fbLlIz^>??gYig* zSujJC*%iOZIFi<(9s3E-Ti?*k?OI1-BU)MQsdC6Ctvp|@Z}^-9F4@$uy4xl=DX>Sy z&KoR7UMELwb;#%W0;})Vebad4Ts<=LTwkuKnjM2-seLi4!{|BXZGx;pQ}@uG=*oce z8~p|ryJ`IkV=wAS4L`UU*W;(HVoJoHK2ZLlBnhGCFB17vNoYh?Ac&gK^6(@YzlO*8;=dXY5`sfhF zq{Lw2efuychmD_|5UO-*I} z*@9Q9eBk2KZ2|FzE2`!m?)~g9PwzcB^l$dX>XF!1wDSu9}Tw^PK4prh5og43|b}&G-9Bb1_rgm^-=R5;SH=p!Axm18DMieG8z(f~We9e*en^~I&%n4`eA3@%ZXjiE`zT+polloW zQl}k%DQEu07n4t>4&D{3A1%L5Z0t(C=gJ?svlZq?hI8Y@PUMSW0rPGWehfE<##L=6 ziY4_IV+i;RbNkWfN4pmu>|BRmzAm^X2)f2<-|1#Fx4?U4NB6qz^l{NOh2i;#-Q8)k zkcH*D{6-%~j2U|*ze=*OK=M;6uUju*-71@`9jG_Az`rAGEW5FXcav|U$MTlYLrH72 zf-JXC#t-toc*ij5Z^(@&jgKgBB zTRct$TkX0h%V#$SNN~8ijI2d{JT_N_i8-ZhwVqp5xfip>Ez79~jLn7A=D?gtFakoY zGv2IrYd^&4*c`@5!V_238_*^j2He3u@a z-zas_Zek1W4Z{0$u(+4+%wFbIK&AXSPcRv#>i%mbjHq*rUT`$1*i9sL#>-TOpw>=+V&eqz> zJv#hgP2Xv~!q4TeEUr=I=}V1ZE(I*XN{Aq*ZonG_?W#NBOd%)3(9-jzs%s=q()2|P z{Mtod)Hsye>K|n*O-zNYhmSY8m{arQIzT8%xdcOA!YhOJdIvn$9M{(AnP{|8r8QQ= zht#=jjElWKR(OQx^N#iEHtm$Xb4aHO_$D#<>K=W^*Uq>y`;ha%q2c6+=k#I8E_TxRdhR^o=X2_MP~c zS%>*%n~E!b4o|8c#p9A*ul%bC1yPqQuIlTsHBSiMW3~karBt zQ%SZ}a;lF8KU*io8_H{8@)}yRN&ND096pR8%qp?EwEBZg5t-It>2&c`#i}$P&j+H0 z{%R7w8iY;xZdVA&xD|I<&P0M>;mZ!iV*Xz?k-%x@*PD)CJDS)U{Ouch`Agfo1fqvx z`x$F6O?WrQ7$(dfy@P%;Azu~fvmk884>hN5e01YZcB3)w5+3zJh}W}aFyPXbh>$Qk zh3;lqGXJLy&(C!OvzMXsmR~NP<^dua^t`|rCZ(3q8!9_F#(Omh=QuH!DM-+j`c2#Y zv}XUZYA=7YvAo>>X)8J-0Z_MXAc3MhK=c_BaD($GVOAwJYiR|iS&TX>b9Sc@$qsf# zJGDc>w7cbJv$AlOVsso9NGElQIhxldAB;?nIg5Ei%3*gyF!nzEg#L#d7lP82_h}d~ z3_|T)hlKY6(!I?>g7+mR#iUVv5&K~sE($%*gR%>jVKh!8?Y#?m(xRsCpKdv~^GR2a zC81~#VKcsH6+>C?8{Se-t1TT4=hP&K$AfW92425;M+p=D76+I~sT>!Rax8n+e&}lA zx~PNwVykJOm(Sef)6={ zxEdyHA5RML6-6|>MH41B@jp3B;29_{5q+P(AG2H;A#!u(YYPU@L>T1mc^S<7>54>0C=#m=RC1BdSYWjbZ@L9LfU>XomPK# zZwfwJfT;cT1l%=C*Rkm8Hn;gyjK_l(7uq~r^``R!;(6%V0eJqV{(4Npev(;JS+`n& z1nLYg+{J!90?~p08uEXfVswA08>ZLi!){E|CDcI7#_`a9U{U?WWtwk(i~nw1aDw>( zF#FD*2VLwS06p8b%Q^uzT!s%+4&Ho3adb&pz5kah9)9XYEso!9!K?)lu|n%zQFE7R zeXs^A@9(1XLu0C3+J|>OUb^bU`K8YlM8j=G+ZZRvqh60|5WzU=AGu*>)x1n%bP9gngv4 zqd3c;i{}F2h@qvdB`r(~wc^&065Q-!uueZ_#Giae{p>-~LeBK@(}}T;qX(aC!UH07 z%$}S#>{_ce(|%AU7k}c8s#wiXkUeNA=)6n5TJ0@FqqzhO8{o?ZN665$q&J64zh;cy zjtdhFnHiS;D*Z;ahG$F5Dxl$6(#{Re^6**mHhW!X#Rp4CM9&sLlgnu zf^V(h<4HT( z(s_3X%co$vpA)2>87d)x#52RQQ?}r(eHT`nGWoJEl2m-;Vdq5*;l0B2`IfFuqGp46 z8L?f|+1Rh&SfKk$>IVs(qxGR7fr(R>bMPk^vg?;Q{2UJ!O&r!8?Q7{-66w`^Yrpn- zDVp7Nf~iB699_ND&OvLA4+%V;%}(Q0wi(EtQXqMVKF>^6ps!7yaeh7*hQ{;Utbs|6AIg#Zg;bg*s}F^WJ04xBOlQR7bR5%E_IGSL0& zbLel>Ecx6Hx=?@A>(iNnr_qmEY)`&_PVu~3KUbF-2UW$7BH<*w*?&e+c7;vQe)+SW zSmDot>VHA}f1k!Ay&I=9@8>IwqEEj(2zgAHqc?#KnDkLQGMDE87Lp!Tj?0|i9z}V! zW6g!JwW+z|bd*mxEt$S*CotA~1WPk(RS_M@I?I7!jO_DU+uoIfQP8{hp>EmUl^)p_ z=xJSGwYD~?8CI;C=wW1C%E3^}^Te0ClGqfhe0+bC&@@404{K`?#>nRqbqYZ>E=$h-ZT6>F-~;ydME9d;tY)S+0{44B?mSlLr``Icg%wvMApDwjhL8_JckVq;OJM2#OH zS-q-bK^jd8A#U4>6W>BC2p1=oc%$^qPX=@Omy6s!x}{ZA#D((eaAQM~06QS3B&B4C zU7k07artOc?JXtgJ3Kwg9ub37!kP$lt~ryebIfIRP`j*G23+{#HBW|Z(XrN3T!5Xb z8m6j|cLsItNMVi-zC6;#Qs$lukzJ+ZSr6>PMh)=vgFfS-wR5%)f#QHA+%3h$4>%8< z7`s=`TZJRZr}+9VSONz|=qd>ePNtSt-8#*g~f`)M2zj(6Onz5mx3cGf)ICzly9}F31 zlr_124=bR|Y6 zywrCjUU(tg2?oEQ5|Vpp1K7O0e03sgtzvtzYYx&+APHJK3%#pM^$(^iwxVGKN?1Ku zZJ0ECx^$DL=6^2qWF@E%!{rbGrjDV7h`M>z^&^!TE0>~4S;o+|*Dm<)JGJtkfEfG} z>n>Lt-u6Hf43C9_nFJEUW}1I)^ie4v@A@Dr3x2E6`rX0&;bbP{IS71w$A6fN*I7aj zuaYwoIsXcV_4pTGJ`hrC%;wf4!LpHTpCYh>vQ_EVtalpmy$UpvGcXI$x@iy)ep3g~ z3jrn}_d)9Me#qva!|{G)N3bXKLrwTU4cNv8(*GqVk$^ zje#uTp8j6U4J`qMvo@Q&>*YjJD__3NTh|<_;RIbJpmW{phP_~gaGSW<$r^aN*_)8J zDpstwD7egTmlp|)q`NT4#AiIUl(tW}6DldS(;=5Ja|(S2)1Q_ptD~$5%ggI3Zegom zOP1WD3KMzic=FlTCDX7)>kU~9=ePF?Csw7BT$3(>7|$UH66yp(Z|z~q(>1oRS++0O z^pWkjk?jKPu4c4!EVKGgr|WR3@5Y&kU?=zx>*3Ds5x72gjUHoa!hIgO6h%IPVx+{2 zA_AFOh`*@AGM|W42#xX8Jh^6BXzb8N^-9SD9X3PaSJO2!_40`7Q+UWL2J(kcJhgJa z1t(3b@trhoR2F|M0RQzG(5l4x$MnS*l{DRX&Ha*W0jU;bUG;kaqp49GUV(ccjhceh z+LkTXjfx2E;d+1ZkK$d#sJyPCRcDkhbg3Geb)!12q}$zimCU&K%{}sDSooaA`kHM2 zi~(yDsst%C1`;N*Z8Av1%JgbvTUiESxHG@4T~1m}T+DCRB(`0R%CCtA@G8lzo(!zV zHVo0%T$gyR6|Ph0*Tz|5l5dBhEMI^GuyQ3-LboD)(XOJ|y{Kx0?`S0NSy z`LY|Y!sHk|dez{!89yCb-ZD%)x$xKeCW;_vhH%r=*O$#+V+9Pw_c%r&z8&7kGh9dR~0+;(@>mGvt>@C>B) z8KRS4Y-SN077vNzA7bvl1#QbpEn>RZC$ON&8ynl@xPRXUYyPeC(L(9hDF66F5%UC{ znT3^SLLK$^m@r@s-5_@%*SjW_bwecYP9~EPty)2TR{bbW7VxCPnX-!>6~8o*MR3y7%Jt`#@Ga1C`L0oCHUeGU9R+t*8QfVI*;+Q; z-+E-mokCB}L2tYsG&);U&`;T3{jEp!(7*%%=Y;PNU(SZ|GBEjX9aJ9rPPL_UdY5bk z4rYh`|HnvwcSzXk0&as|J9yVc?^AK?gx-6b$8x3>X2z<5US1*Z1(ciV!)^UrXSTo# z9aIxJ2NrawH%8_ z;xNbrs8&a~m|n0zG9pz=1EIVM6{O-daXi0gY!K zM|fIhtA2U;3*q<2Za!kOfpx_6JfNUJE2gbg)J}wXyFOjmlTXh^Qz3rjX=)SydG34- zru;lNJ(qN#{^Oed=dqf~tB~F3o)vl%U|`b9xtz3LelP6`8yR88S8|lNgjx&&hQQY) z3Kow_{pT3_^*VMp!%3n#G05ppZ7$f^_8P+FBT9sD24e7JnPB#wcO1q5`@wQcln?DW zI`Y?fX7#w^q5^WWUBZV5bOSxyzu=lY8?`H~T6KJVBaA16C&4|ihn5UaXStSX70};$ z4YT8hsh*S9A9M@e!cKEuftHoQ?0ltBKhCB4^;%bcd7khVYt-Xmi_msm8Lb}Li;g;W zTFzD3bOjS8JW@G6 zpoJ_4sE6hBYtZrn^+{%6J&PjmdQ`w8+%OpvAF1~@8>dzyah}1aiMy2%k`FwfLv;vm zi$lZj^VVSeACxjlVw7OGM5%>94bRMYr+CwrY)c_Eey-9tPp#uN2s3kKZjNjMoN#tp zK8Tc9_BsbQ&rwWh>xowBJ*~~PX1V8uMYW|x3LfrYCWt#Fkgdlq^t8MlRi}Y{il7>^l&l%jI7m%b2_?LHTW{S$PkBzdK-!aCaoW09Qv;sp&i2?BK zxg;FJo!~VvOONjZ<_jn@+|t(t2RXRcjK8Y+OKZ1LY1k*efAw;>_^=v&a{LN`z-b+x zIM`ORzPZp%)xlHUetVZM&bndAS!8>_lU<7Lm5q(o%;fzLi#P_hTbL#+)~n2ZK+tL( zYAJM{svq=YXfQVr0*Q~(CK|s_yNw){2dJ>hMe9pvlRbKh=TDs=EH<(|u?0q~7U<57 zS*uYL5QMeh^|`*6b&EQ&oHbf6g+@5H!lY0qVD~JQ`V<6}#I2If4C>C$?;-&>`Xh^w zg2idGa39v<@&-(XZ2|h*TE^siiWY)dkDszoFdh;Y90kj;Oyj*NHDr?>7`xJX|1b&1 z&Psmg{kIzt14Ewuy`uCFFf(2ReQ(I}&oR|c`drSHwL-G@;JSVM?0uJ9{(;gDA0C;w zG4f0Rs3dPiG#`5T56_M{(FH4z`C2a&X-f<(d6NsnM6ihM*XxDB(t9-n%N|j?<}dcj1pJUU^+<uS@H(+9B=FH7eyN}q^Apv^!-Xmyc-mQ74 zDy+%DebDSf`|Bm=#*}F0F*U@EEGyE18H3vWx;$QNc7SCTTCJO*#X-?89gl;t!H z#o!aE2oITST{Xf9^4d_JJbozqH2hDe;xHmZibvW1A_SpAV%@WK=YpUeRXj*ZMEgm*eLOo z*-*BItJ3X$2WyQ-!Cgr~Gz@@D)^V!~2?W!P-8MWwkvd8Io=^4QyK|}KcPv{}e@tlQ z-Sd(7l;d)pngq>+9bwJ3ivfH@qo*i*ljauUMap^aasP!+IvC}BYxo`%omJD(1Cro? ziY0=RmAd)+W#36N7@s~|WfX)CXB?|wD*XN~^pj)V$?lsy=%PLnI6MTCkWjjlEAYn9 ztt}bEOXw~o7@`0ie*um$>`yEOB&* z__;#l8C(^dDfHaGZXQNM*vDVQ{nWU15h38Aaf2-rMFRjf*+YJtRrR6{yhPaBinwdI zlZ4+9xCk#lpgTE60&P~{C6nJEffS`w3>N%^j1@XhKUDV3@F&68LQsf7^H!jEvvGdEnTMd%r(HX7FiB znFS1AUBu`%zH(*$^WPSc`HjsyZwvMFuhYbDE}EM}$cZrTeMACA>+rp0vK9E3%I&R- zpKLC}9N@$h%S0x|BXR)-kXRt;|Bh__zLdPce=H~70@HU9&ym0nuCN=u1DlyKW+izfWbOdMdh`cdYM|9>S5#wR~$_AKxLW$-jiAYCGgfE_%D~vkB~qs8K^U? ze#sy|{3kAj@G>wc@yE;x7o}juq&R3yw_M)H8vo~rU}t?2iTNfH6zqQmdvA=A!V3m`@PIrUs+;L-F#|-@>}d9 Z-t;}gRC=E^4_STjqNgS1G!{UP{|`#PaNz&| literal 0 HcmV?d00001 diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image002.jpg b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/image002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c91edd2a85de461fff30a4700fefbe5cd4e6e1f3 GIT binary patch literal 30378 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 E0P1^_4FCWD literal 0 HcmV?d00001 diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/item0010.xml b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/item0010.xml new file mode 100644 index 00000000..c8543fbf --- /dev/null +++ b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/item0010.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/props011.xml b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/props011.xml new file mode 100644 index 00000000..38cf3e4b --- /dev/null +++ b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/props011.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/themedata.thmx b/redist/Help/Net_Regular_Expression_Plug-in_About_box_files/themedata.thmx new file mode 100644 index 0000000000000000000000000000000000000000..c2dd8c12f543e366e400e460e992377dd3c1ad27 GIT binary patch literal 3104 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 Tj><>?03G#qqE?RseSiBCYAr;+ literal 0 HcmV?d00001 diff --git a/src/EncCnvtrs/AutoConfigDialog.Designer.cs b/src/EncCnvtrs/AutoConfigDialog.Designer.cs index 7f8ab867..9d29eaec 100755 --- a/src/EncCnvtrs/AutoConfigDialog.Designer.cs +++ b/src/EncCnvtrs/AutoConfigDialog.Designer.cs @@ -550,7 +550,7 @@ private void InitializeComponent(SilEncConverters40.WebBrowserAdaptor webBrowser this.checkBoxICURegularExpression.Name = "checkBoxICURegularExpression"; this.checkBoxICURegularExpression.Size = new System.Drawing.Size(138, 17); this.checkBoxICURegularExpression.TabIndex = 3; - this.checkBoxICURegularExpression.Text = "ICU Regular &Expression"; + this.checkBoxICURegularExpression.Text = "Regular &Expression"; this.checkBoxICURegularExpression.UseVisualStyleBackColor = true; this.checkBoxICURegularExpression.CheckedChanged += new System.EventHandler(this.SomethingChanged); // diff --git a/src/EncCnvtrs/AutoConfigDialog.cs b/src/EncCnvtrs/AutoConfigDialog.cs index 2629db03..16564ad9 100755 --- a/src/EncCnvtrs/AutoConfigDialog.cs +++ b/src/EncCnvtrs/AutoConfigDialog.cs @@ -454,26 +454,46 @@ protected virtual void AddConverterMapping() { // remove any existing converter by the name we're about to give it (probably not necessary). System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(FriendlyName)); - if (ShouldRemoveBeforeAdd) - m_aECs.Remove(FriendlyName); - // if it was originally under a different name... - if (!String.IsNullOrEmpty(m_strOriginalFriendlyName) && (m_strOriginalFriendlyName != FriendlyName)) - { - // ... remove that too (this one probably *is* necessary to remove old stuff) - m_aECs.Remove(m_strOriginalFriendlyName); - } + try + { + // TODO: this is causing problems, bkz any converter can be a step in a compound converter, + // and if you call Remove here, it removes it from any compound converter that references it. + // But is it really necessary to remove it if only the data changes and not the name... + // UPDATE: It appears that if we do AddConverterMappingSub and it already exists with a given name + // the entry will be updated, so we don't need this anyway + // UPDATE2: but if this is a compound converter, then it will append the steps to those already existing + // rather than replacing them, so we do need to remove the existing steps. But we can't do that + // without calling m_aECs.Remove, and we can't change the behavior of Remove or add a new way to do that, + // bkz when this is running in, for example, Paratext, it's using a version of the EncConverters core that + // it loaded and can't use a possible newer one that has this change (this causes 'method doesn't exist' + // kind of errors). + if (ShouldRemoveBeforeAdd) + m_aECs.Remove(FriendlyName); + + // if it was originally under a different name... (YES, in this case, we have to remove it) + if (!String.IsNullOrEmpty(m_strOriginalFriendlyName) && (m_strOriginalFriendlyName != FriendlyName)) + { + // ... remove that too (this one probably *is* necessary to remove old stuff) + m_aECs.Remove(m_strOriginalFriendlyName); + } - // have the sub-classes do their thing to add it - AddConverterMappingSub(); + // have the sub-classes do their thing to add it + AddConverterMappingSub(); - // if it worked, then ... - // ... indicate that now this converter is in the repository - IsInRepository = true; + // if it worked, then ... + // ... indicate that now this converter is in the repository + IsInRepository = true; - // and save the name so we can clear it out if need be later - m_strOriginalFriendlyName = FriendlyName; - } + // and save the name so we can clear it out if need be later + m_strOriginalFriendlyName = FriendlyName; + } + catch (Exception ex) + { + MessageBox.Show(String.Format("Couldn't add converter to repository! Reason: {0}", ex.Message), + EncConverters.cstrCaption); + } + } // allow subclasses to define whether we should remove records before adding them // (e.g. SpellFixer is already added, so we don't want to remove it or we'll clobber the diff --git a/src/EncCnvtrs/CmpdAutoConfigDialog.cs b/src/EncCnvtrs/CmpdAutoConfigDialog.cs index 42b24b7c..622df0d2 100755 --- a/src/EncCnvtrs/CmpdAutoConfigDialog.cs +++ b/src/EncCnvtrs/CmpdAutoConfigDialog.cs @@ -99,7 +99,8 @@ bool bIsInRepository } IsModified = false; - m_bAllStepsAreBidirectional = !EncConverters.IsUnidirectional(m_aEC.ConversionType); + if (m_aEC != null) + m_bAllStepsAreBidirectional = !EncConverters.IsUnidirectional(m_aEC.ConversionType); } } diff --git a/src/EncCnvtrs/EncCnvtrs 2010.csproj b/src/EncCnvtrs/EncCnvtrs 2010.csproj index b3261290..7888b9f9 100644 --- a/src/EncCnvtrs/EncCnvtrs 2010.csproj +++ b/src/EncCnvtrs/EncCnvtrs 2010.csproj @@ -222,6 +222,14 @@ + + Form + + + + + NetRegexAutoConfigDialog.cs + Code @@ -299,6 +307,9 @@ Designer FallbackAutoConfigDialog.cs + + NetRegexAutoConfigDialog.cs + ImplTypeList.cs Designer diff --git a/src/EncCnvtrs/EncConverters.cs b/src/EncCnvtrs/EncConverters.cs index d0b1c3ce..c6c8f290 100755 --- a/src/EncCnvtrs/EncConverters.cs +++ b/src/EncCnvtrs/EncConverters.cs @@ -73,7 +73,8 @@ public class EncConverters : Hashtable, IEncConverters public const string strTypeSILmap = "SIL.map"; public const string strTypeSILcp = "cp"; public const string strTypeSILcomp = "SIL.comp"; - public const string strTypeSILicuTrans = "ICU.trans"; + public const string strTypeSILNetRegex = "SIL.netRegex"; + public const string strTypeSILicuTrans = "ICU.trans"; public const string strTypeSILicuConv = "ICU.conv"; public const string strTypeSILicuRegex = "ICU.regex"; public const string strTypeSILPyScript = "SIL.PyScript"; diff --git a/src/EncCnvtrs/NetRegexAutoConfigDialog.Designer.cs b/src/EncCnvtrs/NetRegexAutoConfigDialog.Designer.cs new file mode 100644 index 00000000..f4bcd2f8 --- /dev/null +++ b/src/EncCnvtrs/NetRegexAutoConfigDialog.Designer.cs @@ -0,0 +1,671 @@ +using System.ComponentModel; +using System.Windows.Forms; + +namespace SilEncConverters40 +{ + partial class NetRegexAutoConfigDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + // This code was NOT generated! + // So feel free to modify it as needed. + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.textBoxReplaceWith = new System.Windows.Forms.TextBox(); + this.labelSearchFor = new System.Windows.Forms.Label(); + this.textBoxSearchFor = new System.Windows.Forms.TextBox(); + this.buttonPopupHelper = new System.Windows.Forms.Button(); + this.labelReplaceWith = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.comboBoxPreviousSearches = new System.Windows.Forms.ComboBox(); + this.buttonDeleteSavedExpression = new System.Windows.Forms.Button(); + this.linkLabelOpenQuickReference = new System.Windows.Forms.LinkLabel(); + this.groupBoxRegexOptions = new System.Windows.Forms.GroupBox(); + this.flowLayoutPanelOptions = new System.Windows.Forms.FlowLayoutPanel(); + this.checkBoxIgnoreCase = new System.Windows.Forms.CheckBox(); + this.checkBoxMultiline = new System.Windows.Forms.CheckBox(); + this.checkBoxSingleLine = new System.Windows.Forms.CheckBox(); + this.checkBoxExplicitCapture = new System.Windows.Forms.CheckBox(); + this.checkBoxIgnorePatternWhitespace = new System.Windows.Forms.CheckBox(); + this.checkBoxRightToLeft = new System.Windows.Forms.CheckBox(); + this.checkBoxECMAScript = new System.Windows.Forms.CheckBox(); + this.checkBoxCultureInvariant = new System.Windows.Forms.CheckBox(); + this.contextMenuRegexChars = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripAnyChar = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip0orMore = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip0or1FewAsPossible = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip0orMoreFewAsPossible = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip1orMore = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip1orMoreFewAsPossible = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatch0or1AsFewAsPossible = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchNtimes = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchAtLeastNtimes = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchN2Mtimes = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchAtLeastNtimesAsFewAsPossible = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchN2MtimesAsFewAsPossible = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripMatchAtBeginningOfLine = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchEndOfLine = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchWordBoundary = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchNonWordBoundary = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchDecimalDigit = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchNonDecimalDigit = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchWhiteSpace = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchNonWhiteSpace = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripMatchOneOf = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchNoneOf = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchOneOfRange = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchOr = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMatchUchar = new System.Windows.Forms.ToolStripMenuItem(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.tabControl.SuspendLayout(); + this.tabPageSetup.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.groupBoxRegexOptions.SuspendLayout(); + this.flowLayoutPanelOptions.SuspendLayout(); + this.contextMenuRegexChars.SuspendLayout(); + this.SuspendLayout(); + // + // tabPageSetup + // + this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); + // + // buttonApply + // + this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonApply, true); + // + // buttonCancel + // + this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); + this.helpProvider.SetShowHelp(this.buttonCancel, true); + // + // buttonOK + // + this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonOK, true); + // + // buttonSaveInRepository + // + this.helpProvider.SetHelpString(this.buttonSaveInRepository, "\r\nClick to add this converter to the system repository permanently.\r\n "); + this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.textBoxReplaceWith, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.labelSearchFor, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.textBoxSearchFor, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.buttonPopupHelper, 2, 1); + this.tableLayoutPanel1.Controls.Add(this.labelReplaceWith, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.label1, 0, 5); + this.tableLayoutPanel1.Controls.Add(this.comboBoxPreviousSearches, 1, 5); + this.tableLayoutPanel1.Controls.Add(this.buttonDeleteSavedExpression, 2, 5); + this.tableLayoutPanel1.Controls.Add(this.linkLabelOpenQuickReference, 1, 6); + this.tableLayoutPanel1.Controls.Add(this.groupBoxRegexOptions, 1, 3); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 7; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); + this.tableLayoutPanel1.TabIndex = 1; + // + // textBoxReplaceWith + // + this.textBoxReplaceWith.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxReplaceWith.Location = new System.Drawing.Point(118, 103); + this.textBoxReplaceWith.Name = "textBoxReplaceWith"; + this.textBoxReplaceWith.Size = new System.Drawing.Size(380, 20); + this.textBoxReplaceWith.TabIndex = 3; + this.textBoxReplaceWith.TextChanged += new System.EventHandler(this.controlChangedModified); + // + // labelSearchFor + // + this.labelSearchFor.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelSearchFor.AutoSize = true; + this.labelSearchFor.Location = new System.Drawing.Point(53, 50); + this.labelSearchFor.Name = "labelSearchFor"; + this.labelSearchFor.Size = new System.Drawing.Size(59, 13); + this.labelSearchFor.TabIndex = 0; + this.labelSearchFor.Text = "&Search for:"; + // + // textBoxSearchFor + // + this.textBoxSearchFor.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxSearchFor.Location = new System.Drawing.Point(118, 53); + this.textBoxSearchFor.Name = "textBoxSearchFor"; + this.textBoxSearchFor.Size = new System.Drawing.Size(380, 20); + this.textBoxSearchFor.TabIndex = 1; + this.textBoxSearchFor.TextChanged += new System.EventHandler(this.controlChangedModified); + // + // buttonPopupHelper + // + this.buttonPopupHelper.Location = new System.Drawing.Point(504, 53); + this.buttonPopupHelper.Name = "buttonPopupHelper"; + this.buttonPopupHelper.Size = new System.Drawing.Size(20, 22); + this.buttonPopupHelper.TabIndex = 2; + this.buttonPopupHelper.Text = ">"; + this.buttonPopupHelper.UseVisualStyleBackColor = true; + this.buttonPopupHelper.Click += new System.EventHandler(this.buttonPopupHelper_Click); + // + // labelReplaceWith + // + this.labelReplaceWith.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelReplaceWith.AutoSize = true; + this.labelReplaceWith.Location = new System.Drawing.Point(40, 100); + this.labelReplaceWith.Name = "labelReplaceWith"; + this.labelReplaceWith.Size = new System.Drawing.Size(72, 13); + this.labelReplaceWith.TabIndex = 0; + this.labelReplaceWith.Text = "&Replace with:"; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 286); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(109, 13); + this.label1.TabIndex = 0; + this.label1.Text = "&Previous expressions:"; + // + // comboBoxPreviousSearches + // + this.comboBoxPreviousSearches.Dock = System.Windows.Forms.DockStyle.Fill; + this.comboBoxPreviousSearches.FormattingEnabled = true; + this.comboBoxPreviousSearches.Location = new System.Drawing.Point(118, 289); + this.comboBoxPreviousSearches.Name = "comboBoxPreviousSearches"; + this.comboBoxPreviousSearches.Size = new System.Drawing.Size(380, 21); + this.comboBoxPreviousSearches.TabIndex = 5; + this.comboBoxPreviousSearches.SelectedIndexChanged += new System.EventHandler(this.comboBoxPreviousSearches_SelectedIndexChanged); + // + // buttonDeleteSavedExpression + // + this.buttonDeleteSavedExpression.Location = new System.Drawing.Point(504, 289); + this.buttonDeleteSavedExpression.Name = "buttonDeleteSavedExpression"; + this.buttonDeleteSavedExpression.Size = new System.Drawing.Size(89, 23); + this.buttonDeleteSavedExpression.TabIndex = 6; + this.buttonDeleteSavedExpression.Text = "Delete"; + this.buttonDeleteSavedExpression.UseVisualStyleBackColor = true; + this.buttonDeleteSavedExpression.Click += new System.EventHandler(this.buttonDeleteSavedExpression_Click); + // + // linkLabelOpenQuickReference + // + this.linkLabelOpenQuickReference.AutoSize = true; + this.linkLabelOpenQuickReference.Location = new System.Drawing.Point(118, 344); + this.linkLabelOpenQuickReference.Name = "linkLabelOpenQuickReference"; + this.linkLabelOpenQuickReference.Size = new System.Drawing.Size(205, 13); + this.linkLabelOpenQuickReference.TabIndex = 8; + this.linkLabelOpenQuickReference.TabStop = true; + this.linkLabelOpenQuickReference.Text = ".Net Regular Expression Quick Reference"; + this.linkLabelOpenQuickReference.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelOpenQuickReference_LinkClicked); + // + // groupBoxRegexOptions + // + this.groupBoxRegexOptions.Controls.Add(this.flowLayoutPanelOptions); + this.groupBoxRegexOptions.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBoxRegexOptions.Location = new System.Drawing.Point(118, 153); + this.groupBoxRegexOptions.Name = "groupBoxRegexOptions"; + this.groupBoxRegexOptions.Size = new System.Drawing.Size(380, 100); + this.groupBoxRegexOptions.TabIndex = 9; + this.groupBoxRegexOptions.TabStop = false; + this.groupBoxRegexOptions.Text = "RegexOptions"; + // + // flowLayoutPanelOptions + // + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxIgnoreCase); + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxMultiline); + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxSingleLine); + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxExplicitCapture); + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxIgnorePatternWhitespace); + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxRightToLeft); + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxECMAScript); + this.flowLayoutPanelOptions.Controls.Add(this.checkBoxCultureInvariant); + this.flowLayoutPanelOptions.Dock = System.Windows.Forms.DockStyle.Fill; + this.flowLayoutPanelOptions.Location = new System.Drawing.Point(3, 16); + this.flowLayoutPanelOptions.Name = "flowLayoutPanelOptions"; + this.flowLayoutPanelOptions.Padding = new System.Windows.Forms.Padding(3, 3, 6, 3); + this.flowLayoutPanelOptions.Size = new System.Drawing.Size(374, 81); + this.flowLayoutPanelOptions.TabIndex = 7; + // + // checkBoxIgnoreCase + // + this.checkBoxIgnoreCase.AutoSize = true; + this.checkBoxIgnoreCase.Location = new System.Drawing.Point(6, 6); + this.checkBoxIgnoreCase.Name = "checkBoxIgnoreCase"; + this.checkBoxIgnoreCase.Size = new System.Drawing.Size(82, 17); + this.checkBoxIgnoreCase.TabIndex = 4; + this.checkBoxIgnoreCase.Text = "&Ignore case"; + this.toolTip.SetToolTip(this.checkBoxIgnoreCase, "Check to use case-insensitive matching."); + this.checkBoxIgnoreCase.UseVisualStyleBackColor = true; + this.checkBoxIgnoreCase.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // checkBoxMultiline + // + this.checkBoxMultiline.AutoSize = true; + this.checkBoxMultiline.Location = new System.Drawing.Point(94, 6); + this.checkBoxMultiline.Name = "checkBoxMultiline"; + this.checkBoxMultiline.Size = new System.Drawing.Size(64, 17); + this.checkBoxMultiline.TabIndex = 4; + this.checkBoxMultiline.Text = "&Multiline"; + this.toolTip.SetToolTip(this.checkBoxMultiline, "Use multiline mode, where ^ and $ indicate the beginning and end of each line (in" + + "stead of the beginning and end of the input string)."); + this.checkBoxMultiline.UseVisualStyleBackColor = true; + this.checkBoxMultiline.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // checkBoxSingleLine + // + this.checkBoxSingleLine.AutoSize = true; + this.checkBoxSingleLine.Location = new System.Drawing.Point(164, 6); + this.checkBoxSingleLine.Name = "checkBoxSingleLine"; + this.checkBoxSingleLine.Size = new System.Drawing.Size(71, 17); + this.checkBoxSingleLine.TabIndex = 4; + this.checkBoxSingleLine.Text = "&Singleline"; + this.toolTip.SetToolTip(this.checkBoxSingleLine, "Use single-line mode, where the period (.) matches every character (instead of ev" + + "ery character except \\n)."); + this.checkBoxSingleLine.UseVisualStyleBackColor = true; + this.checkBoxSingleLine.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // checkBoxExplicitCapture + // + this.checkBoxExplicitCapture.AutoSize = true; + this.checkBoxExplicitCapture.Location = new System.Drawing.Point(241, 6); + this.checkBoxExplicitCapture.Name = "checkBoxExplicitCapture"; + this.checkBoxExplicitCapture.Size = new System.Drawing.Size(99, 17); + this.checkBoxExplicitCapture.TabIndex = 4; + this.checkBoxExplicitCapture.Text = "&Explicit Capture"; + this.toolTip.SetToolTip(this.checkBoxExplicitCapture, "Do not capture unnamed groups. The only valid captures are explicitly named or nu" + + "mbered groups of the form (? subexpression)."); + this.checkBoxExplicitCapture.UseVisualStyleBackColor = true; + this.checkBoxExplicitCapture.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // checkBoxIgnorePatternWhitespace + // + this.checkBoxIgnorePatternWhitespace.AutoSize = true; + this.checkBoxIgnorePatternWhitespace.Location = new System.Drawing.Point(6, 29); + this.checkBoxIgnorePatternWhitespace.Name = "checkBoxIgnorePatternWhitespace"; + this.checkBoxIgnorePatternWhitespace.Size = new System.Drawing.Size(153, 17); + this.checkBoxIgnorePatternWhitespace.TabIndex = 4; + this.checkBoxIgnorePatternWhitespace.Text = "&Ignore Pattern Whitespace"; + this.toolTip.SetToolTip(this.checkBoxIgnorePatternWhitespace, "Exclude unescaped white space from the pattern, and enable comments after a numbe" + + "r sign (#)."); + this.checkBoxIgnorePatternWhitespace.UseVisualStyleBackColor = true; + this.checkBoxIgnorePatternWhitespace.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // checkBoxRightToLeft + // + this.checkBoxRightToLeft.AutoSize = true; + this.checkBoxRightToLeft.Location = new System.Drawing.Point(165, 29); + this.checkBoxRightToLeft.Name = "checkBoxRightToLeft"; + this.checkBoxRightToLeft.Size = new System.Drawing.Size(88, 17); + this.checkBoxRightToLeft.TabIndex = 4; + this.checkBoxRightToLeft.Text = "&Right To Left"; + this.toolTip.SetToolTip(this.checkBoxRightToLeft, "Change the search direction. Search moves from right to left instead of from left" + + " to right."); + this.checkBoxRightToLeft.UseVisualStyleBackColor = true; + this.checkBoxRightToLeft.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // checkBoxECMAScript + // + this.checkBoxECMAScript.AutoSize = true; + this.checkBoxECMAScript.Location = new System.Drawing.Point(259, 29); + this.checkBoxECMAScript.Name = "checkBoxECMAScript"; + this.checkBoxECMAScript.Size = new System.Drawing.Size(86, 17); + this.checkBoxECMAScript.TabIndex = 4; + this.checkBoxECMAScript.Text = "&ECMA Script"; + this.toolTip.SetToolTip(this.checkBoxECMAScript, "Enable ECMAScript-compliant behavior for the expression."); + this.checkBoxECMAScript.UseVisualStyleBackColor = true; + this.checkBoxECMAScript.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // checkBoxCultureInvariant + // + this.checkBoxCultureInvariant.AutoSize = true; + this.checkBoxCultureInvariant.Location = new System.Drawing.Point(6, 52); + this.checkBoxCultureInvariant.Name = "checkBoxCultureInvariant"; + this.checkBoxCultureInvariant.Size = new System.Drawing.Size(103, 17); + this.checkBoxCultureInvariant.TabIndex = 4; + this.checkBoxCultureInvariant.Text = "&Culture Invariant"; + this.toolTip.SetToolTip(this.checkBoxCultureInvariant, "Ignore cultural differences in language."); + this.checkBoxCultureInvariant.UseVisualStyleBackColor = true; + this.checkBoxCultureInvariant.CheckedChanged += new System.EventHandler(this.controlChangedModified); + // + // contextMenuRegexChars + // + this.contextMenuRegexChars.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripAnyChar, + this.toolStrip0orMore, + this.toolStrip0or1FewAsPossible, + this.toolStrip0orMoreFewAsPossible, + this.toolStrip1orMore, + this.toolStrip1orMoreFewAsPossible, + this.toolStripMatch0or1AsFewAsPossible, + this.toolStripMatchNtimes, + this.toolStripMatchAtLeastNtimes, + this.toolStripMatchN2Mtimes, + this.toolStripMatchAtLeastNtimesAsFewAsPossible, + this.toolStripMatchN2MtimesAsFewAsPossible, + this.toolStripSeparator1, + this.toolStripMatchAtBeginningOfLine, + this.toolStripMatchEndOfLine, + this.toolStripMatchWordBoundary, + this.toolStripMatchNonWordBoundary, + this.toolStripMatchDecimalDigit, + this.toolStripMatchNonDecimalDigit, + this.toolStripMatchWhiteSpace, + this.toolStripMatchNonWhiteSpace, + this.toolStripSeparator2, + this.toolStripMatchOneOf, + this.toolStripMatchNoneOf, + this.toolStripMatchOneOfRange, + this.toolStripMatchOr, + this.toolStripMatchUchar}); + this.contextMenuRegexChars.Name = "contextMenuRegexChars"; + this.contextMenuRegexChars.Size = new System.Drawing.Size(1068, 566); + // + // toolStripAnyChar + // + this.toolStripAnyChar.Name = "toolStripAnyChar"; + this.toolStripAnyChar.Size = new System.Drawing.Size(1067, 22); + this.toolStripAnyChar.Text = ". Matches any single character except (To match a literal period character (. or" + + " \\u002E), you must precede it with the escape character (\\.))."; + this.toolStripAnyChar.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStrip0orMore + // + this.toolStrip0orMore.Name = "toolStrip0orMore"; + this.toolStrip0orMore.Size = new System.Drawing.Size(1067, 22); + this.toolStrip0orMore.Text = "* Matches the previous element zero or more times."; + this.toolStrip0orMore.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStrip0or1FewAsPossible + // + this.toolStrip0or1FewAsPossible.Name = "toolStrip0or1FewAsPossible"; + this.toolStrip0or1FewAsPossible.Size = new System.Drawing.Size(1067, 22); + this.toolStrip0or1FewAsPossible.Text = "? Matches the previous element zero or one time."; + this.toolStrip0or1FewAsPossible.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStrip0orMoreFewAsPossible + // + this.toolStrip0orMoreFewAsPossible.Name = "toolStrip0orMoreFewAsPossible"; + this.toolStrip0orMoreFewAsPossible.Size = new System.Drawing.Size(1067, 22); + this.toolStrip0orMoreFewAsPossible.Text = "*? Matches the previous element zero or more times, but as few times as possible" + + "."; + this.toolStrip0orMoreFewAsPossible.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStrip1orMore + // + this.toolStrip1orMore.Name = "toolStrip1orMore"; + this.toolStrip1orMore.Size = new System.Drawing.Size(1067, 22); + this.toolStrip1orMore.Text = "+ Matches the previous element one or more times."; + this.toolStrip1orMore.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStrip1orMoreFewAsPossible + // + this.toolStrip1orMoreFewAsPossible.Name = "toolStrip1orMoreFewAsPossible"; + this.toolStrip1orMoreFewAsPossible.Size = new System.Drawing.Size(1067, 22); + this.toolStrip1orMoreFewAsPossible.Text = "+? Matches the previous element one or more times, but as few times as possible." + + ""; + this.toolStrip1orMoreFewAsPossible.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatch0or1AsFewAsPossible + // + this.toolStripMatch0or1AsFewAsPossible.Name = "toolStripMatch0or1AsFewAsPossible"; + this.toolStripMatch0or1AsFewAsPossible.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatch0or1AsFewAsPossible.Text = "?? Matches the previous element zero or one time, but as few times as possible."; + // + // toolStripMatchNtimes + // + this.toolStripMatchNtimes.Name = "toolStripMatchNtimes"; + this.toolStripMatchNtimes.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchNtimes.Text = "{n} Matches the previous element exactly n times."; + this.toolStripMatchNtimes.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchAtLeastNtimes + // + this.toolStripMatchAtLeastNtimes.Name = "toolStripMatchAtLeastNtimes"; + this.toolStripMatchAtLeastNtimes.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchAtLeastNtimes.Text = "{n,} Matches the previous element at least n times."; + this.toolStripMatchAtLeastNtimes.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchN2Mtimes + // + this.toolStripMatchN2Mtimes.Name = "toolStripMatchN2Mtimes"; + this.toolStripMatchN2Mtimes.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchN2Mtimes.Text = "{n,m} Matches the previous element at least n times, but no more than m times."; + this.toolStripMatchN2Mtimes.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchAtLeastNtimesAsFewAsPossible + // + this.toolStripMatchAtLeastNtimesAsFewAsPossible.Name = "toolStripMatchAtLeastNtimesAsFewAsPossible"; + this.toolStripMatchAtLeastNtimesAsFewAsPossible.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchAtLeastNtimesAsFewAsPossible.Text = "{n,}? Matches the previous element at least n times, but as few times as possibl" + + "e."; + this.toolStripMatchAtLeastNtimesAsFewAsPossible.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchN2MtimesAsFewAsPossible + // + this.toolStripMatchN2MtimesAsFewAsPossible.Name = "toolStripMatchN2MtimesAsFewAsPossible"; + this.toolStripMatchN2MtimesAsFewAsPossible.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchN2MtimesAsFewAsPossible.Text = "{n,m}? Matches the previous element between n and m times, but as few times as p" + + "ossible."; + this.toolStripMatchN2MtimesAsFewAsPossible.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(1064, 6); + // + // toolStripMatchAtBeginningOfLine + // + this.toolStripMatchAtBeginningOfLine.Name = "toolStripMatchAtBeginningOfLine"; + this.toolStripMatchAtBeginningOfLine.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchAtBeginningOfLine.Text = "^ By default, the match must start at the beginning of the string; in multiline " + + "mode, it must start at the beginning of the line."; + this.toolStripMatchAtBeginningOfLine.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchEndOfLine + // + this.toolStripMatchEndOfLine.Name = "toolStripMatchEndOfLine"; + this.toolStripMatchEndOfLine.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchEndOfLine.Text = "$ By default, the match must occur at the end of the string or before \\n at the " + + "end of the string; in multiline mode, it must occur before the end of the line o" + + "r before \\n at the end of the line."; + this.toolStripMatchEndOfLine.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchWordBoundary + // + this.toolStripMatchWordBoundary.Name = "toolStripMatchWordBoundary"; + this.toolStripMatchWordBoundary.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchWordBoundary.Text = "\\b The match must occur on a boundary between a \\w (alphanumeric) and a \\W (nona" + + "lphanumeric) character."; + this.toolStripMatchWordBoundary.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchNonWordBoundary + // + this.toolStripMatchNonWordBoundary.Name = "toolStripMatchNonWordBoundary"; + this.toolStripMatchNonWordBoundary.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchNonWordBoundary.Text = "\\B The match must not occur on a \\b boundary."; + this.toolStripMatchNonWordBoundary.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchDecimalDigit + // + this.toolStripMatchDecimalDigit.Name = "toolStripMatchDecimalDigit"; + this.toolStripMatchDecimalDigit.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchDecimalDigit.Text = "\\d Matches any decimal digit."; + this.toolStripMatchDecimalDigit.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchNonDecimalDigit + // + this.toolStripMatchNonDecimalDigit.Name = "toolStripMatchNonDecimalDigit"; + this.toolStripMatchNonDecimalDigit.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchNonDecimalDigit.Text = "\\D Matches any character other than a decimal digit."; + this.toolStripMatchNonDecimalDigit.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchWhiteSpace + // + this.toolStripMatchWhiteSpace.Name = "toolStripMatchWhiteSpace"; + this.toolStripMatchWhiteSpace.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchWhiteSpace.Text = "\\s Matches any white-space character."; + this.toolStripMatchWhiteSpace.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchNonWhiteSpace + // + this.toolStripMatchNonWhiteSpace.Name = "toolStripMatchNonWhiteSpace"; + this.toolStripMatchNonWhiteSpace.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchNonWhiteSpace.Text = "\\S Matches any non-white-space character."; + this.toolStripMatchNonWhiteSpace.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(1064, 6); + // + // toolStripMatchOneOf + // + this.toolStripMatchOneOf.Name = "toolStripMatchOneOf"; + this.toolStripMatchOneOf.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchOneOf.Text = "[chars] Matches any single character in character_group. By default, the match i" + + "s case-sensitive."; + this.toolStripMatchOneOf.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchNoneOf + // + this.toolStripMatchNoneOf.Name = "toolStripMatchNoneOf"; + this.toolStripMatchNoneOf.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchNoneOf.Text = "[^chars] Negation: Matches any single character that is not in character_group. " + + "By default, characters in character_group are case-sensitive."; + this.toolStripMatchNoneOf.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchOneOfRange + // + this.toolStripMatchOneOfRange.Name = "toolStripMatchOneOfRange"; + this.toolStripMatchOneOfRange.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchOneOfRange.Text = "[first-last] Character range: Matches any single character in the range from fir" + + "st to last. (e.g. [A-Z] is any upper case Latin alphabetic character)"; + this.toolStripMatchOneOfRange.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchOr + // + this.toolStripMatchOr.Name = "toolStripMatchOr"; + this.toolStripMatchOr.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchOr.Text = "| Matches any one element separated by the vertical bar (|) character. (e.g. \'A|" + + "B\' matches either A or B)"; + this.toolStripMatchOr.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // toolStripMatchUchar + // + this.toolStripMatchUchar.Name = "toolStripMatchUchar"; + this.toolStripMatchUchar.Size = new System.Drawing.Size(1067, 22); + this.toolStripMatchUchar.Text = "\\uHHHH Match the character with the hex value HHHH (e.g. \\u0020 matches the SPAC" + + "E character)"; + this.toolStripMatchUchar.Click += new System.EventHandler(this.OnRegexHelperMenuClick); + // + // NetRegexAutoConfigDialog + // + this.ClientSize = new System.Drawing.Size(634, 479); + this.Name = "NetRegexAutoConfigDialog"; + this.Controls.SetChildIndex(this.tabControl, 0); + this.Controls.SetChildIndex(this.buttonApply, 0); + this.Controls.SetChildIndex(this.buttonCancel, 0); + this.Controls.SetChildIndex(this.buttonOK, 0); + this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); + this.tabControl.ResumeLayout(false); + this.tabPageSetup.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.groupBoxRegexOptions.ResumeLayout(false); + this.flowLayoutPanelOptions.ResumeLayout(false); + this.flowLayoutPanelOptions.PerformLayout(); + this.contextMenuRegexChars.ResumeLayout(false); + this.ResumeLayout(false); + + } + + private System.Windows.Forms.Label labelSearchFor; + private System.Windows.Forms.TextBox textBoxSearchFor; + private ContextMenuStrip contextMenuRegexChars; + private ToolStripMenuItem toolStripAnyChar; + private Button buttonPopupHelper; + private ToolStripMenuItem toolStrip0orMore; + private ToolStripMenuItem toolStrip0or1FewAsPossible; + private ToolStripMenuItem toolStrip0orMoreFewAsPossible; + private ToolStripMenuItem toolStrip1orMore; + private ToolStripMenuItem toolStrip1orMoreFewAsPossible; + private ToolStripMenuItem toolStripMatchNtimes; + private ToolStripMenuItem toolStripMatchAtLeastNtimes; + private ToolStripMenuItem toolStripMatchN2Mtimes; + private ToolStripSeparator toolStripSeparator1; + private ToolStripMenuItem toolStripMatchAtBeginningOfLine; + private ToolStripMenuItem toolStripMatchEndOfLine; + private ToolStripMenuItem toolStripMatchWordBoundary; + private ToolStripMenuItem toolStripMatchNonWordBoundary; + private ToolStripMenuItem toolStripMatchDecimalDigit; + private ToolStripMenuItem toolStripMatchNonDecimalDigit; + private ToolStripMenuItem toolStripMatchWhiteSpace; + private ToolStripMenuItem toolStripMatchNonWhiteSpace; + private ToolStripSeparator toolStripSeparator2; + private ToolStripMenuItem toolStripMatchOneOf; + private ToolStripMenuItem toolStripMatchNoneOf; + private ToolStripMenuItem toolStripMatchOneOfRange; + private ToolStripMenuItem toolStripMatchOr; + private ToolStripMenuItem toolStripMatchUchar; + private Label labelReplaceWith; + private TextBox textBoxReplaceWith; + private CheckBox checkBoxIgnoreCase; + private Label label1; + private ComboBox comboBoxPreviousSearches; + private Button buttonDeleteSavedExpression; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + + #endregion + + private FlowLayoutPanel flowLayoutPanelOptions; + private CheckBox checkBoxMultiline; + private CheckBox checkBoxSingleLine; + private CheckBox checkBoxExplicitCapture; + private CheckBox checkBoxIgnorePatternWhitespace; + private CheckBox checkBoxRightToLeft; + private CheckBox checkBoxECMAScript; + private CheckBox checkBoxCultureInvariant; + private ToolTip toolTip; + private ToolStripMenuItem toolStripMatch0or1AsFewAsPossible; + private ToolStripMenuItem toolStripMatchAtLeastNtimesAsFewAsPossible; + private ToolStripMenuItem toolStripMatchN2MtimesAsFewAsPossible; + private LinkLabel linkLabelOpenQuickReference; + private GroupBox groupBoxRegexOptions; + } +} diff --git a/src/EncCnvtrs/NetRegexAutoConfigDialog.cs b/src/EncCnvtrs/NetRegexAutoConfigDialog.cs new file mode 100644 index 00000000..f9d5da30 --- /dev/null +++ b/src/EncCnvtrs/NetRegexAutoConfigDialog.cs @@ -0,0 +1,244 @@ +// Created by Jim Kornelsen on Dec 6 2011 +// +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.IO; +using ECInterfaces; +using System.Text.RegularExpressions; +using static SilEncConverters40.NetRegexEncConverter; + +//uncomment the following line for verbose debugging output using Console.WriteLine +//#define VERBOSE_DEBUGGING + +namespace SilEncConverters40 +{ + public partial class NetRegexAutoConfigDialog : SilEncConverters40.AutoConfigDialog + { + public NetRegexAutoConfigDialog ( + IEncConverters aECs, + string strDisplayName, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strLhsEncodingId, + string strRhsEncodingId, + int lProcessTypeFlags, + bool bIsInRepository) + { +#if VERBOSE_DEBUGGING + Console.WriteLine("NetRegexAutoConfigDialog ctor BEGIN"); +#endif + InitializeComponent(); +#if VERBOSE_DEBUGGING + Console.WriteLine("Initialized NetRegexAutoConfigDialog component."); +#endif + base.Initialize ( + aECs, + NetRegexEncConverter.strHtmlFilename, + strDisplayName, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strLhsEncodingId, + strRhsEncodingId, + lProcessTypeFlags | (int)ProcessTypeFlags.ICURegularExpression, // not really ICU, but do we really need another one? + bIsInRepository); +#if VERBOSE_DEBUGGING + Console.WriteLine("Initialized base."); +#endif + + LoadComboBoxFromSettings(comboBoxPreviousSearches, Properties.Settings.Default.RecentRegExpressions); + comboBoxPreviousSearches.SelectedIndex = 0; + + // if we're editing a converter, then set the controls per the ConverterSpec and mark it as unmodified + if (m_bEditMode) + { +#if VERBOSE_DEBUGGING + Console.WriteLine("Edit mode"); +#endif + System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(ConverterIdentifier)); + InitRegexControls(ConverterIdentifier); + + IsModified = false; + } + + m_bInitialized = true; +#if VERBOSE_DEBUGGING + Console.WriteLine("NetRegexAutoConfigDialog ctor END"); +#endif + } + + private void InitRegexControls(string strConverterIdentifier) + { + if (!ParseConverterIdentifier(strConverterIdentifier, out string strFindWhat, out string strReplaceWith, out RegexOptions options)) + return; + + textBoxSearchFor.Text = strFindWhat; + textBoxReplaceWith.Text = strReplaceWith; + checkBoxIgnoreCase.Checked = (options & RegexOptions.IgnoreCase) == RegexOptions.IgnoreCase; + checkBoxMultiline.Checked = (options & RegexOptions.Multiline) == RegexOptions.Multiline; + checkBoxSingleLine.Checked = (options & RegexOptions.Singleline) == RegexOptions.Singleline; + checkBoxExplicitCapture.Checked = (options & RegexOptions.ExplicitCapture) == RegexOptions.ExplicitCapture; + checkBoxIgnorePatternWhitespace.Checked = (options & RegexOptions.IgnorePatternWhitespace) == RegexOptions.IgnorePatternWhitespace; + checkBoxRightToLeft.Checked = (options & RegexOptions.RightToLeft) == RegexOptions.RightToLeft; + checkBoxECMAScript.Checked = (options & RegexOptions.ECMAScript) == RegexOptions.ECMAScript; + checkBoxCultureInvariant.Checked = (options & RegexOptions.CultureInvariant) == RegexOptions.CultureInvariant; + } + + public NetRegexAutoConfigDialog( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData) + { + InitializeComponent(); + base.Initialize ( + aECs, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strTestData); + } + + private string GetConverterSpec + { + get + { + var options = RegexOptions.None; + if (checkBoxIgnoreCase.Checked) + options |= RegexOptions.IgnoreCase; + if (checkBoxMultiline.Checked) + options |= RegexOptions.Multiline; + if (checkBoxSingleLine.Checked) + options |= RegexOptions.Singleline; + if (checkBoxExplicitCapture.Checked) + options |= RegexOptions.ExplicitCapture; + if (checkBoxIgnorePatternWhitespace.Checked) + options |= RegexOptions.IgnorePatternWhitespace; + if (checkBoxRightToLeft.Checked) + options |= RegexOptions.RightToLeft; + if (checkBoxECMAScript.Checked) + options |= RegexOptions.ECMAScript; + if (checkBoxCultureInvariant.Checked) + options |= RegexOptions.CultureInvariant; + + var str = $"{{{textBoxSearchFor.Text}}}{RegexDelimiter}{{{textBoxReplaceWith.Text}}};{(int)options}"; + return str; + } + } + + // this method is called either when the user clicks the "Apply" or "OK" buttons *OR* if she + // tries to switch to the Test or Advanced tab. This is the dialog's one opportunity + // to make sure that the user has correctly configured a legitimate converter. + protected override bool OnApply() + { +#if VERBOSE_DEBUGGING + Console.Error.WriteLine("OnApply() BEGIN"); +#endif + + // if we're actually on the setup tab, then do some further checking as well. + if (tabControl.SelectedTab == tabPageSetup) + { + var strSearchFor = textBoxSearchFor.Text; + // only do these message boxes if we're on the Setup tab itself, because if this OnApply + // is being called as a result of the user switching to the Test tab, that code will + // already put up an error message and we don't need two error messages. + if (String.IsNullOrEmpty(strSearchFor)) + { + MessageBox.Show(this, "Enter a regular expression first!", EncConverters.cstrCaption); + return false; + } + } + + // Get the converter identifier from the Setup tab controls. + ConverterIdentifier = GetConverterSpec; + + UpdateRecentRegExpressions(ConverterIdentifier); +#if VERBOSE_DEBUGGING + Console.Error.WriteLine("OnApply() END"); +#endif + return base.OnApply(); + } + + private void UpdateRecentRegExpressions(string strConverterIdentifier) + { + if (!Properties.Settings.Default.RecentRegExpressions.Contains(strConverterIdentifier)) + { + Properties.Settings.Default.RecentRegExpressions.Add(strConverterIdentifier); + Properties.Settings.Default.Save(); + LoadComboBoxFromSettings(comboBoxPreviousSearches, Properties.Settings.Default.RecentRegExpressions); + } + comboBoxPreviousSearches.SelectedItem = strConverterIdentifier; + } + + protected override string ProgID + { + get { return typeof(NetRegexEncConverter).FullName; } + } + + protected override string ImplType + { + get { return EncConverters.strTypeSILNetRegex; } + } + + protected override string DefaultFriendlyName + { + // as the default, make it the same as the reg expression + get { return ConverterIdentifier; } + } + + private void controlChangedModified(object sender, EventArgs e) + { + if (!m_bInitialized || IsModified) + return; + + IsModified = true; + } + + private void buttonPopupHelper_Click(object sender, EventArgs e) + { + contextMenuRegexChars.Show(MousePosition); + } + + private void OnRegexHelperMenuClick(object sender, EventArgs e) + { + var tsmi = sender as ToolStripMenuItem; + Debug.Assert(tsmi != null, "tsmi != null"); + var text = tsmi.Text; + var nLength = text.IndexOf(" "); + var str = text.Substring(0, nLength); + textBoxSearchFor.Text += str; + } + + private void comboBoxPreviousSearches_SelectedIndexChanged(object sender, EventArgs e) + { + if (!m_bInitialized) + return; + + var strConverterSpec = comboBoxPreviousSearches.SelectedItem.ToString(); + InitRegexControls(strConverterSpec); + } + + private void buttonDeleteSavedExpression_Click(object sender, EventArgs e) + { + DeleteSelectedItemFromComboBoxAndUpdateSettings(comboBoxPreviousSearches, + Properties.Settings.Default.RecentRegExpressions); + + Properties.Settings.Default.Save(); + } + + private void linkLabelOpenQuickReference_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(Properties.Resources.NetRegexQuickReferenceLink); + } + } +} + diff --git a/src/EncCnvtrs/NetRegexAutoConfigDialog.resx b/src/EncCnvtrs/NetRegexAutoConfigDialog.resx new file mode 100644 index 00000000..534d985a --- /dev/null +++ b/src/EncCnvtrs/NetRegexAutoConfigDialog.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 637, 17 + + + 17, 17 + + + 341, 17 + + + 450, 17 + + + 68 + + \ No newline at end of file diff --git a/src/EncCnvtrs/NetRegexEncConverter.cs b/src/EncCnvtrs/NetRegexEncConverter.cs new file mode 100644 index 00000000..b9d70853 --- /dev/null +++ b/src/EncCnvtrs/NetRegexEncConverter.cs @@ -0,0 +1,195 @@ +// Created by Jim Kornelsen on Dec 6 2011 +// 28-Nov-11 JDK Wrap Perl expression and write in temp file, rather than requiring input file. +// +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using ECInterfaces; // for IEncConverter +using SilEncConverters40.Properties; + +namespace SilEncConverters40 +{ + /// + /// Managed Net Regex EncConverter + /// + public class NetRegexEncConverter : EncConverter + { + #region Const Definitions + public const string DisplayName = ".Net Regular Expression"; + public const string strHtmlFilename = "Net_Regular_Expression_Plug-in_About_box.htm"; + + public const string RegexDelimiter = "->"; + + public bool TransliteratorInitialized { get; set; } + + // the regular express definining the Converter identifier: + // {}->{}; + // e.g. + // {[aeiou]}->{V};1 + // (meaing: for convert latin vowels to 'V' and make it case insensitive. That is, 1 = RegexOption.IgnoreCase) + private static readonly Regex _reParseConverterIdentifier = new("{(.+)}->{(.*)};?(.*)"); + private Regex _reConverter; + private string _replaceWith; + + #endregion Const Definitions + + #region Initialization + /// + /// The class constructor. + public NetRegexEncConverter() + : base (typeof(NetRegexEncConverter).FullName, EncConverters.strTypeSILNetRegex) + { + } + + public override void Initialize( + string converterName, + string converterSpec, + ref string lhsEncodingID, + ref string rhsEncodingID, + ref ConvType conversionType, + ref Int32 processTypeFlags, + Int32 codePageInput, + Int32 codePageOutput, + bool bAdding) + { + Util.DebugWriteLine(this, "BEGIN"); + // let the base class have first stab at it + base.Initialize(converterName, converterSpec, ref lhsEncodingID, ref rhsEncodingID, + ref conversionType, ref processTypeFlags, codePageInput, codePageOutput, bAdding ); + + // this is the only conversion type this converter supports + m_eConversionType = conversionType = ConvType.Unicode_to_Unicode; + + // both sides are (supposed to be) Unicode + if (String.IsNullOrEmpty(lhsEncodingID)) + lhsEncodingID = m_strLhsEncodingID = EncConverters.strDefUnicodeEncoding; + if (String.IsNullOrEmpty(rhsEncodingID)) + rhsEncodingID = m_strRhsEncodingID = EncConverters.strDefUnicodeEncoding; + + // not really an "ICU" regular expression, but the UI now just + // shows this as 'Regular Expression' and it applies to this and the ICU one. + processTypeFlags |= (int)ProcessTypeFlags.ICURegularExpression; + + TransliteratorInitialized = false; // so it has to be reinitialized (But only once) + + Util.DebugWriteLine(this, "END"); + } + #endregion Initialization + + #region Misc helpers + protected override EncodingForm DefaultUnicodeEncForm(bool bForward, bool bLHS) + { + return EncodingForm.UTF16; + } + + internal static bool ParseConverterIdentifier(string strConverterSpec, + out string strFindWhat, out string strReplaceWith, out RegexOptions options) + { + var match = _reParseConverterIdentifier.Match(strConverterSpec); + if (match.Success) + { + var strOptions = match.Groups[3].Value; + if (String.IsNullOrEmpty(strOptions)) + { + options = RegexOptions.None; + } + else + { + options = (RegexOptions)int.Parse(strOptions); + } + + strFindWhat = match.Groups[1].Value; + strReplaceWith = match.Groups[2].Value; + + return true; + } + else + { + options = RegexOptions.None; + strFindWhat = strReplaceWith = null; + return false; + } + } + + protected unsafe void Load(string converterIdentifier) + { + Util.DebugWriteLine(this, "BEGIN"); + + if (TransliteratorInitialized) + return; + + if (!ParseConverterIdentifier(converterIdentifier, out string findWhat, out string replaceWith, out RegexOptions options)) + { + throw new ApplicationException($"{DisplayName} not properly configured! converterName: {converterIdentifier} (should be in the format {{}}->{{}};)"); + } + + _replaceWith = replaceWith; + _reConverter = new Regex(findWhat, options | RegexOptions.Compiled); + + TransliteratorInitialized = true; // so we don't to do this with each call to Convert + + Util.DebugWriteLine(this, "END"); + } + + #endregion Misc helpers + + #region Abstract Base Class Overrides + protected override void PreConvert + ( + EncodingForm eInEncodingForm, + ref EncodingForm eInFormEngine, + EncodingForm eOutEncodingForm, + ref EncodingForm eOutFormEngine, + ref NormalizeFlags eNormalizeOutput, + bool bForward + ) + { + // let the base class do it's thing first + base.PreConvert( eInEncodingForm, ref eInFormEngine, + eOutEncodingForm, ref eOutFormEngine, + ref eNormalizeOutput, bForward); + + // do the load at this point. + Load(ConverterIdentifier); + } + + protected override unsafe void DoConvert + ( + byte* lpInBuffer, + int nInLen, + byte* lpOutBuffer, + ref int rnOutLen + ) + { + // we need to put it *back* into a string for the conversion + byte[] baIn = new byte[nInLen]; + ECNormalizeData.ByteStarToByteArr(lpInBuffer, nInLen, baIn); + char[] caIn = Encoding.Unicode.GetChars(baIn); + + // here's our input string + var strInput = new string(caIn); + + var strOutput = _reConverter.Replace(strInput, _replaceWith); + + StringToProperByteStar(strOutput, lpOutBuffer, ref rnOutLen); + } + + protected override string GetConfigTypeName + { + get { return typeof(NetRegexEncConverterConfig).AssemblyQualifiedName; } + } + + [CLSCompliant(false)] + private static unsafe void StringToProperByteStar(string strOutput, byte* lpOutBuffer, ref int rnOutLen) + { + int nLen = strOutput.Length * 2; + if (nLen > (int)rnOutLen) + EncConverters.ThrowError(ErrStatus.OutputBufferFull); + rnOutLen = nLen; + ECNormalizeData.StringToByteStar(strOutput, lpOutBuffer, rnOutLen, false); + } + #endregion Abstract Base Class Overrides + } +} diff --git a/src/EncCnvtrs/NetRegexEncConverterConfig.cs b/src/EncCnvtrs/NetRegexEncConverterConfig.cs new file mode 100644 index 00000000..2157b470 --- /dev/null +++ b/src/EncCnvtrs/NetRegexEncConverterConfig.cs @@ -0,0 +1,61 @@ +// Created by Jim Kornelsen on Dec 6 2011 +// +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; // for the class attributes +using ECInterfaces; // for IEncConverter + +namespace SilEncConverters40 +{ + public class NetRegexEncConverterConfig : EncConverterConfig + { + public NetRegexEncConverterConfig() + : base + ( + typeof(NetRegexEncConverter).FullName, + NetRegexEncConverter.DisplayName, + NetRegexEncConverter.strHtmlFilename, + ProcessTypeFlags.ICURegularExpression + ) + { + } + + public override bool Configure + ( + IEncConverters aECs, + string strFriendlyName, + ConvType eConversionType, + string strLhsEncodingID, + string strRhsEncodingID + ) + { + var form = new NetRegexAutoConfigDialog ( + aECs, m_strDisplayName, m_strFriendlyName, + m_strConverterID, m_eConversionType, + BestGuessEncoding(m_strLhsEncodingID, strLhsEncodingID, EncConverters.strDefUnicodeEncoding), + BestGuessEncoding(m_strRhsEncodingID, strRhsEncodingID, EncConverters.strDefUnicodeEncoding), + m_lProcessType, m_bIsInRepository); + + return Configure(form); + } + + public override void DisplayTestPage + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + InitializeFromThis(ref strFriendlyName, ref strConverterIdentifier, + ref eConversionType, ref strTestData); + + NetRegexAutoConfigDialog form = new NetRegexAutoConfigDialog(aECs, strFriendlyName, + strConverterIdentifier, eConversionType, strTestData); + + base.DisplayTestPage(form); + } + } +} diff --git a/src/EncCnvtrs/Properties/Resources.Designer.cs b/src/EncCnvtrs/Properties/Resources.Designer.cs index 7cc635f6..03b87d3f 100755 --- a/src/EncCnvtrs/Properties/Resources.Designer.cs +++ b/src/EncCnvtrs/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace SilEncConverters40.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -132,6 +132,15 @@ internal static string ConvTypeReturnsHelpString { } } + /// + /// Looks up a localized string similar to https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference. + /// + internal static string NetRegexQuickReferenceLink { + get { + return ResourceManager.GetString("NetRegexQuickReferenceLink", resourceCulture); + } + } + /// /// Looks up a localized string similar to ///This box displays the result of the conversion using the selected converter given some data diff --git a/src/EncCnvtrs/Properties/Resources.resx b/src/EncCnvtrs/Properties/Resources.resx index 9e7ed259..d5a4e0d6 100755 --- a/src/EncCnvtrs/Properties/Resources.resx +++ b/src/EncCnvtrs/Properties/Resources.resx @@ -164,6 +164,9 @@ Choose the encoding type for the output of the table/map: either Unicode or Lega For example, if this is an Unicode encoding converter, then the output will be Unicode encoding. + + https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference + This box displays the result of the conversion using the selected converter given some data diff --git a/src/EncCnvtrs/Properties/Settings.Designer.cs b/src/EncCnvtrs/Properties/Settings.Designer.cs index 37d98313..445aa4b4 100644 --- a/src/EncCnvtrs/Properties/Settings.Designer.cs +++ b/src/EncCnvtrs/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace SilEncConverters40.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -22,5 +22,22 @@ public static Settings Default { return defaultInstance; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute(@" + + {[aeiou]}->{V};1 + {[^aeiou]}->{C};1 + {[\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD]}->{}; +")] + public global::System.Collections.Specialized.StringCollection RecentRegExpressions { + get { + return ((global::System.Collections.Specialized.StringCollection)(this["RecentRegExpressions"])); + } + set { + this["RecentRegExpressions"] = value; + } + } } } diff --git a/src/EncCnvtrs/Properties/Settings.settings b/src/EncCnvtrs/Properties/Settings.settings index 8e615f25..daec514a 100644 --- a/src/EncCnvtrs/Properties/Settings.settings +++ b/src/EncCnvtrs/Properties/Settings.settings @@ -1,5 +1,14 @@  - + - + + + <?xml version="1.0" encoding="utf-16"?> +<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <string>{[aeiou]}-&gt;{V};1</string> + <string>{[^aeiou]}-&gt;{C};1</string> + <string>{[\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD]}-&gt;{};</string> +</ArrayOfString> + + \ No newline at end of file diff --git a/src/EncCnvtrs/SelectConverter.cs b/src/EncCnvtrs/SelectConverter.cs index 9d7ccd18..ae7d7ba5 100755 --- a/src/EncCnvtrs/SelectConverter.cs +++ b/src/EncCnvtrs/SelectConverter.cs @@ -39,9 +39,9 @@ public class SelectConverter : System.Windows.Forms.Form static private string strInstallerPathKey = "InstallerPath"; private System.Windows.Forms.Button buttonCreateNew; private System.Windows.Forms.ContextMenuStrip contextMenu; - private System.Windows.Forms.ToolStripItem menuItemEdit; - private System.Windows.Forms.ToolStripItem menuItemDelete; - private System.Windows.Forms.ListBox listBoxExistingConverters; + private ToolStripMenuItem menuItemEdit; + private ToolStripMenuItem menuItemDelete; + private System.Windows.Forms.ListBox listBoxExistingConverters; private TableLayoutPanel tableLayoutPanel1; private CheckBox checkBoxShowTooltips; private HelpProvider helpProvider; @@ -54,8 +54,8 @@ public class SelectConverter : System.Windows.Forms.Form private TextBox textBoxDataPreview; protected byte[] m_byPreviewData = null; - private ToolStripItem menuItemTest; - protected internal ContextMenuStrip contextMenuStripPreview; + private ToolStripMenuItem menuItemTest; + protected internal ContextMenuStrip contextMenuStripPreview; private ToolStripMenuItem changeFontToolStripMenuItem; private ToolStripSeparator toolStripSeparator1; private ToolStripMenuItem copyToolStripMenuItem; @@ -66,7 +66,8 @@ public class SelectConverter : System.Windows.Forms.Form protected internal FontDialog fontDialog; protected string m_strPreviewData = null; private Timer timerTooltip; - protected string m_strFontName = null; + private ToolStripMenuItem menuItemRefresh; + protected string m_strFontName = null; public SelectConverter(EncConverters aECs, ConvType eConversionTypeFilter, string strChooseConverterDialogTitle, byte[] abyPreviewData, string strFontName) @@ -287,7 +288,6 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - Util.DebugWriteLine(this, "BEGIN"); this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SelectConverter)); this.labelInstruction = new System.Windows.Forms.Label(); @@ -310,7 +310,7 @@ private void InitializeComponent() this.flowLayoutPanelCodePage = new System.Windows.Forms.FlowLayoutPanel(); this.labelCodePageInput = new System.Windows.Forms.Label(); this.labelCodePageOutput = new System.Windows.Forms.Label(); - this.contextMenu = new System.Windows.Forms.ContextMenuStrip(); + this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.menuItemEdit = new System.Windows.Forms.ToolStripMenuItem(); this.menuItemTest = new System.Windows.Forms.ToolStripMenuItem(); this.menuItemDelete = new System.Windows.Forms.ToolStripMenuItem(); @@ -328,14 +328,16 @@ private void InitializeComponent() this.helpProvider = new System.Windows.Forms.HelpProvider(); this.fontDialog = new System.Windows.Forms.FontDialog(); this.timerTooltip = new System.Windows.Forms.Timer(this.components); + this.menuItemRefresh = new System.Windows.Forms.ToolStripMenuItem(); this.groupBoxOptions.SuspendLayout(); this.flowLayoutPanelCodePage.SuspendLayout(); + this.contextMenu.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); this.contextMenuStripPreview.SuspendLayout(); this.SuspendLayout(); - // + // // labelInstruction - // + // this.labelInstruction.Anchor = System.Windows.Forms.AnchorStyles.Left; this.tableLayoutPanel1.SetColumnSpan(this.labelInstruction, 4); this.labelInstruction.Location = new System.Drawing.Point(3, 0); @@ -343,14 +345,14 @@ private void InitializeComponent() this.labelInstruction.Size = new System.Drawing.Size(439, 23); this.labelInstruction.TabIndex = 0; this.labelInstruction.Text = "Choose an existing converter from the list below or click Add New to add a new on" + - "e:"; + "e:"; this.labelInstruction.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // + // // buttonCancel - // + // this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel the selection of a converter and return to the callin" + - "g program"); + "g program"); this.buttonCancel.Location = new System.Drawing.Point(448, 364); this.buttonCancel.Name = "buttonCancel"; this.helpProvider.SetShowHelp(this.buttonCancel, true); @@ -359,12 +361,12 @@ private void InitializeComponent() this.buttonCancel.Text = "&Cancel"; this.toolTips.SetToolTip(this.buttonCancel, "Cancel selection"); this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click); - // + // // buttonOK - // + // this.buttonOK.Enabled = false; this.helpProvider.SetHelpString(this.buttonOK, "Click this button to choose the selected converter and return to the calling prog" + - "ram"); + "ram"); this.buttonOK.Location = new System.Drawing.Point(367, 364); this.buttonOK.Name = "buttonOK"; this.helpProvider.SetShowHelp(this.buttonOK, true); @@ -373,16 +375,16 @@ private void InitializeComponent() this.buttonOK.Text = "&OK"; this.toolTips.SetToolTip(this.buttonOK, "Click here to choose the selected converter"); this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); - // + // // toolTips - // + // this.toolTips.AutomaticDelay = 50; this.toolTips.AutoPopDelay = 30000; this.toolTips.InitialDelay = 1000; this.toolTips.ReshowDelay = 500; - // + // // checkBoxReverse - // + // this.checkBoxReverse.Enabled = false; this.helpProvider.SetHelpString(this.checkBoxReverse, "Check this option if the reverse conversion is to be performed"); this.checkBoxReverse.Location = new System.Drawing.Point(26, 24); @@ -393,11 +395,11 @@ private void InitializeComponent() this.checkBoxReverse.Text = "&Reverse direction (for bidirectional converters)"; this.toolTips.SetToolTip(this.checkBoxReverse, "Convert in the reverse direction"); this.checkBoxReverse.CheckedChanged += new System.EventHandler(this.checkBoxReverse_CheckedChanged); - // + // // labelNormalizationType - // - this.labelNormalizationType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + // + this.labelNormalizationType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.labelNormalizationType.Enabled = false; this.labelNormalizationType.Location = new System.Drawing.Point(210, 24); this.labelNormalizationType.Name = "labelNormalizationType"; @@ -405,12 +407,12 @@ private void InitializeComponent() this.labelNormalizationType.TabIndex = 4; this.labelNormalizationType.Text = "Normalize Output:"; this.toolTips.SetToolTip(this.labelNormalizationType, "Controls the normalization of the converted data."); - // + // // checkBoxDebug - // + // this.checkBoxDebug.Enabled = false; this.helpProvider.SetHelpString(this.checkBoxDebug, "This option allows you to troubleshoot the selected converter with respect to the" + - " data being send to and received from the underlying conversion engine"); + " data being send to and received from the underlying conversion engine"); this.checkBoxDebug.Location = new System.Drawing.Point(26, 58); this.checkBoxDebug.Name = "checkBoxDebug"; this.helpProvider.SetShowHelp(this.checkBoxDebug, true); @@ -418,11 +420,11 @@ private void InitializeComponent() this.checkBoxDebug.TabIndex = 5; this.checkBoxDebug.Text = "&Debug"; this.toolTips.SetToolTip(this.checkBoxDebug, "Show debug information during conversion"); - // + // // buttonCreateNew - // + // this.helpProvider.SetHelpString(this.buttonCreateNew, "Click this button to add a new converter to the list (including existing map file" + - "s)"); + "s)"); this.buttonCreateNew.Location = new System.Drawing.Point(3, 364); this.buttonCreateNew.Name = "buttonCreateNew"; this.helpProvider.SetShowHelp(this.buttonCreateNew, true); @@ -431,14 +433,14 @@ private void InitializeComponent() this.buttonCreateNew.Text = "&Add New"; this.toolTips.SetToolTip(this.buttonCreateNew, "Add a new converter to the list (including existing map files)"); this.buttonCreateNew.Click += new System.EventHandler(this.buttonCreateNew_Click); - // + // // radioButtonFullyComposed - // - this.radioButtonFullyComposed.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + // + this.radioButtonFullyComposed.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.radioButtonFullyComposed.Enabled = false; this.helpProvider.SetHelpString(this.radioButtonFullyComposed, "The output of the conversion is returned to the client application in Unicode Nor" + - "malization Form \'Fully Composed\'"); + "malization Form \'Fully Composed\'"); this.radioButtonFullyComposed.Location = new System.Drawing.Point(226, 88); this.radioButtonFullyComposed.Name = "radioButtonFullyComposed"; this.helpProvider.SetShowHelp(this.radioButtonFullyComposed, true); @@ -446,15 +448,15 @@ private void InitializeComponent() this.radioButtonFullyComposed.TabIndex = 3; this.radioButtonFullyComposed.Text = "Fully Co&mposed"; this.toolTips.SetToolTip(this.radioButtonFullyComposed, "Output of the conversion is returned in Unicode Normalization Form \'Fully Compose" + - "d\'"); - // + "d\'"); + // // radioButtonFullyDecomposed - // - this.radioButtonFullyDecomposed.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + // + this.radioButtonFullyDecomposed.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.radioButtonFullyDecomposed.Enabled = false; this.helpProvider.SetHelpString(this.radioButtonFullyDecomposed, "The output of the conversion is returned to the client application in Unicode Nor" + - "malization Form \'Fully Decomposed\'"); + "malization Form \'Fully Decomposed\'"); this.radioButtonFullyDecomposed.Location = new System.Drawing.Point(226, 64); this.radioButtonFullyDecomposed.Name = "radioButtonFullyDecomposed"; this.helpProvider.SetShowHelp(this.radioButtonFullyDecomposed, true); @@ -462,15 +464,15 @@ private void InitializeComponent() this.radioButtonFullyDecomposed.TabIndex = 2; this.radioButtonFullyDecomposed.Text = "&Fully Decomposed"; this.toolTips.SetToolTip(this.radioButtonFullyDecomposed, "Return data in Unicode Normalization Form \'Fully Decomposed\'"); - // + // // radioButtonNone - // - this.radioButtonNone.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + // + this.radioButtonNone.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.radioButtonNone.Checked = true; this.radioButtonNone.Enabled = false; this.helpProvider.SetHelpString(this.radioButtonNone, "The output of the conversion is returned to the client application without change" + - ""); + ""); this.radioButtonNone.Location = new System.Drawing.Point(226, 40); this.radioButtonNone.Name = "radioButtonNone"; this.helpProvider.SetShowHelp(this.radioButtonNone, true); @@ -479,9 +481,9 @@ private void InitializeComponent() this.radioButtonNone.TabStop = true; this.radioButtonNone.Text = "&None"; this.toolTips.SetToolTip(this.radioButtonNone, "Output of the conversion is returned without change"); - // + // // buttonLaunchOptionsInstaller - // + // this.helpProvider.SetHelpString(this.buttonLaunchOptionsInstaller, "Click this button to launch the Converter Options Installer"); this.buttonLaunchOptionsInstaller.Location = new System.Drawing.Point(165, 364); this.buttonLaunchOptionsInstaller.Name = "buttonLaunchOptionsInstaller"; @@ -492,9 +494,9 @@ private void InitializeComponent() this.toolTips.SetToolTip(this.buttonLaunchOptionsInstaller, "Launch the Converter Options Installer"); this.buttonLaunchOptionsInstaller.Visible = false; this.buttonLaunchOptionsInstaller.Click += new System.EventHandler(this.buttonLaunchOptionsInstaller_Click); - // + // // checkBoxShowTooltips - // + // this.checkBoxShowTooltips.AutoSize = true; this.checkBoxShowTooltips.Checked = true; this.checkBoxShowTooltips.CheckState = System.Windows.Forms.CheckState.Checked; @@ -508,36 +510,36 @@ private void InitializeComponent() this.toolTips.SetToolTip(this.checkBoxShowTooltips, "Show ToolTips when checked"); this.checkBoxShowTooltips.UseVisualStyleBackColor = true; this.checkBoxShowTooltips.CheckedChanged += new System.EventHandler(this.checkBoxShowTooltips_CheckedChanged); - // + // // textBoxCodePageInput - // + // this.textBoxCodePageInput.Location = new System.Drawing.Point(3, 16); this.textBoxCodePageInput.Name = "textBoxCodePageInput"; this.textBoxCodePageInput.Size = new System.Drawing.Size(80, 20); this.textBoxCodePageInput.TabIndex = 7; this.toolTips.SetToolTip(this.textBoxCodePageInput, "this field shows the code page used for the legacy data that is the input to the " + - "conversion. Typical values are \'0\' (default system code page), \'42\' (symbol font" + - "s), \'1252\' (English operating systems)"); + "conversion. Typical values are \'0\' (default system code page), \'42\' (symbol font" + + "s), \'1252\' (English operating systems)"); this.textBoxCodePageInput.Visible = false; this.textBoxCodePageInput.TextChanged += new System.EventHandler(this.textBoxCodePageInput_TextChanged); - // + // // textBoxCodePageOutput - // + // this.textBoxCodePageOutput.Location = new System.Drawing.Point(3, 55); this.textBoxCodePageOutput.Name = "textBoxCodePageOutput"; this.textBoxCodePageOutput.Size = new System.Drawing.Size(80, 20); this.textBoxCodePageOutput.TabIndex = 7; this.toolTips.SetToolTip(this.textBoxCodePageOutput, "this field shows the code page used for the legacy data that is the output of the" + - " conversion. Typical values are \'0\' (default system code page), \'42\' (symbol fon" + - "ts), \'1252\' (English operating systems)"); + " conversion. Typical values are \'0\' (default system code page), \'42\' (symbol fon" + + "ts), \'1252\' (English operating systems)"); this.textBoxCodePageOutput.Visible = false; this.textBoxCodePageOutput.TextChanged += new System.EventHandler(this.textBoxCodePageOutput_TextChanged); - // + // // buttonPreview - // + // this.buttonPreview.Enabled = false; this.helpProvider.SetHelpString(this.buttonPreview, "Click this button to open a preview window showing the result of the conversion w" + - "ith the selected converter."); + "ith the selected converter."); this.buttonPreview.Location = new System.Drawing.Point(84, 364); this.buttonPreview.Name = "buttonPreview"; this.helpProvider.SetShowHelp(this.buttonPreview, true); @@ -545,12 +547,12 @@ private void InitializeComponent() this.buttonPreview.TabIndex = 11; this.buttonPreview.Text = "&Preview >>"; this.toolTips.SetToolTip(this.buttonPreview, "Click this button to see a preview pane below (not supported by all client progra" + - "ms)"); + "ms)"); this.buttonPreview.UseVisualStyleBackColor = true; this.buttonPreview.Click += new System.EventHandler(this.buttonPreview_Click); - // + // // groupBoxOptions - // + // this.tableLayoutPanel1.SetColumnSpan(this.groupBoxOptions, 5); this.groupBoxOptions.Controls.Add(this.flowLayoutPanelCodePage); this.groupBoxOptions.Controls.Add(this.checkBoxDebug); @@ -566,9 +568,9 @@ private void InitializeComponent() this.groupBoxOptions.TabIndex = 6; this.groupBoxOptions.TabStop = false; this.groupBoxOptions.Text = "Conversion Options"; - // + // // flowLayoutPanelCodePage - // + // this.flowLayoutPanelCodePage.Controls.Add(this.labelCodePageInput); this.flowLayoutPanelCodePage.Controls.Add(this.textBoxCodePageInput); this.flowLayoutPanelCodePage.Controls.Add(this.labelCodePageOutput); @@ -578,9 +580,9 @@ private void InitializeComponent() this.flowLayoutPanelCodePage.Name = "flowLayoutPanelCodePage"; this.flowLayoutPanelCodePage.Size = new System.Drawing.Size(131, 100); this.flowLayoutPanelCodePage.TabIndex = 8; - // + // // labelCodePageInput - // + // this.labelCodePageInput.AutoSize = true; this.labelCodePageInput.Location = new System.Drawing.Point(3, 0); this.labelCodePageInput.Name = "labelCodePageInput"; @@ -588,9 +590,9 @@ private void InitializeComponent() this.labelCodePageInput.TabIndex = 6; this.labelCodePageInput.Text = "&Input Code Page"; this.labelCodePageInput.Visible = false; - // + // // labelCodePageOutput - // + // this.labelCodePageOutput.AutoSize = true; this.labelCodePageOutput.Location = new System.Drawing.Point(3, 39); this.labelCodePageOutput.Name = "labelCodePageOutput"; @@ -598,50 +600,59 @@ private void InitializeComponent() this.labelCodePageOutput.TabIndex = 6; this.labelCodePageOutput.Text = "Output Code Pa&ge"; this.labelCodePageOutput.Visible = false; - // + // // contextMenu - // + // this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.menuItemEdit, this.menuItemTest, - this.menuItemDelete}); - // + this.menuItemDelete, + this.menuItemRefresh}); + this.contextMenu.Name = "contextMenu"; + this.contextMenu.Size = new System.Drawing.Size(181, 114); + // // menuItemEdit - // + // + this.menuItemEdit.Name = "menuItemEdit"; + this.menuItemEdit.Size = new System.Drawing.Size(180, 22); this.menuItemEdit.Text = "&Edit"; this.menuItemEdit.Click += new System.EventHandler(this.menuItemEdit_Click); - // + // // menuItemTest - // + // + this.menuItemTest.Name = "menuItemTest"; + this.menuItemTest.Size = new System.Drawing.Size(180, 22); this.menuItemTest.Text = "&Test"; this.menuItemTest.Click += new System.EventHandler(this.menuItemTest_Click); - // + // // menuItemDelete - // + // + this.menuItemDelete.Name = "menuItemDelete"; + this.menuItemDelete.Size = new System.Drawing.Size(180, 22); this.menuItemDelete.Text = "&Delete"; this.menuItemDelete.Click += new System.EventHandler(this.menuItemDelete_Click); - // + // // listBoxExistingConverters - // + // this.tableLayoutPanel1.SetColumnSpan(this.listBoxExistingConverters, 5); this.listBoxExistingConverters.Dock = System.Windows.Forms.DockStyle.Fill; this.helpProvider.SetHelpString(this.listBoxExistingConverters, "This list shows all of the converters currently in the system repository"); this.listBoxExistingConverters.Location = new System.Drawing.Point(3, 26); this.listBoxExistingConverters.Name = "listBoxExistingConverters"; this.helpProvider.SetShowHelp(this.listBoxExistingConverters, true); - this.listBoxExistingConverters.Size = new System.Drawing.Size(542, 186); + this.listBoxExistingConverters.Size = new System.Drawing.Size(542, 198); this.listBoxExistingConverters.Sorted = true; this.listBoxExistingConverters.TabIndex = 9; - this.listBoxExistingConverters.MouseUp += new System.Windows.Forms.MouseEventHandler(this.listBoxExistingConverters_MouseUp); this.listBoxExistingConverters.SelectedIndexChanged += new System.EventHandler(this.listBoxExistingConverters_SelectedIndexChanged); this.listBoxExistingConverters.DoubleClick += new System.EventHandler(this.listBoxExistingConverters_DoubleClick); this.listBoxExistingConverters.MouseMove += new System.Windows.Forms.MouseEventHandler(this.listBoxExistingConverters_MouseMove); - // + this.listBoxExistingConverters.MouseUp += new System.Windows.Forms.MouseEventHandler(this.listBoxExistingConverters_MouseUp); + // // tableLayoutPanel1 - // - this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + // + this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); this.tableLayoutPanel1.ColumnCount = 5; this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 81F)); this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); @@ -668,9 +679,9 @@ private void InitializeComponent() this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 30F)); this.tableLayoutPanel1.Size = new System.Drawing.Size(548, 478); this.tableLayoutPanel1.TabIndex = 10; - // + // // textBoxDataPreview - // + // this.tableLayoutPanel1.SetColumnSpan(this.textBoxDataPreview, 5); this.textBoxDataPreview.ContextMenuStrip = this.contextMenuStripPreview; this.textBoxDataPreview.Dock = System.Windows.Forms.DockStyle.Fill; @@ -682,9 +693,9 @@ private void InitializeComponent() this.textBoxDataPreview.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.textBoxDataPreview.Size = new System.Drawing.Size(542, 82); this.textBoxDataPreview.TabIndex = 12; - // + // // contextMenuStripPreview - // + // this.contextMenuStripPreview.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.changeFontToolStripMenuItem, this.toolStripSeparator1, @@ -694,65 +705,72 @@ private void InitializeComponent() this.toolStripSeparator3, this.right2LeftToolStripMenuItem}); this.contextMenuStripPreview.Name = "contextMenuStrip"; - this.contextMenuStripPreview.Size = new System.Drawing.Size(200, 110); - // + this.contextMenuStripPreview.Size = new System.Drawing.Size(211, 110); + // // changeFontToolStripMenuItem - // + // this.changeFontToolStripMenuItem.Name = "changeFontToolStripMenuItem"; - this.changeFontToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.changeFontToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.changeFontToolStripMenuItem.Text = "Change &Font"; this.changeFontToolStripMenuItem.ToolTipText = "Click here to change the display font for this text box"; this.changeFontToolStripMenuItem.Click += new System.EventHandler(this.changeFontToolStripMenuItem_Click); - // + // // toolStripSeparator1 - // + // this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(196, 6); - // + this.toolStripSeparator1.Size = new System.Drawing.Size(207, 6); + // // copyToolStripMenuItem - // + // this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; - this.copyToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.copyToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.copyToolStripMenuItem.Text = "Copy"; this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); - // + // // toolStripSeparator2 - // + // this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(196, 6); - // + this.toolStripSeparator2.Size = new System.Drawing.Size(207, 6); + // // selectAllToolStripMenuItem - // + // this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem"; - this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.selectAllToolStripMenuItem.Text = "Select All"; this.selectAllToolStripMenuItem.Click += new System.EventHandler(this.selectAllToolStripMenuItem_Click); - // + // // toolStripSeparator3 - // + // this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(196, 6); - // + this.toolStripSeparator3.Size = new System.Drawing.Size(207, 6); + // // right2LeftToolStripMenuItem - // + // this.right2LeftToolStripMenuItem.CheckOnClick = true; this.right2LeftToolStripMenuItem.Name = "right2LeftToolStripMenuItem"; - this.right2LeftToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.right2LeftToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.right2LeftToolStripMenuItem.Text = "&Right to left reading order"; this.right2LeftToolStripMenuItem.Click += new System.EventHandler(this.right2LeftToolStripMenuItem_Click); - // + // // fontDialog - // + // this.fontDialog.AllowScriptChange = false; this.fontDialog.ShowColor = true; - // + // // timerTooltip - // + // this.timerTooltip.Interval = 500; this.timerTooltip.Tick += new System.EventHandler(this.timerTooltip_Tick); - // + // + // menuItemRefresh + // + this.menuItemRefresh.Name = "menuItemRefresh"; + this.menuItemRefresh.Size = new System.Drawing.Size(180, 22); + this.menuItemRefresh.Text = "&Refresh List"; + this.menuItemRefresh.Click += new System.EventHandler(this.menuItemRefresh_Click); + // // SelectConverter - // + // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(572, 502); this.Controls.Add(this.tableLayoutPanel1); @@ -766,12 +784,12 @@ private void InitializeComponent() this.groupBoxOptions.ResumeLayout(false); this.flowLayoutPanelCodePage.ResumeLayout(false); this.flowLayoutPanelCodePage.PerformLayout(); + this.contextMenu.ResumeLayout(false); this.tableLayoutPanel1.ResumeLayout(false); this.tableLayoutPanel1.PerformLayout(); this.contextMenuStripPreview.ResumeLayout(false); this.ResumeLayout(false); - Util.DebugWriteLine(this, "END"); } #endregion @@ -1070,7 +1088,13 @@ private void menuItemDelete_Click(object sender, System.EventArgs e) } } - private void listBoxExistingConverters_SelectedIndexChanged(object sender, EventArgs e) + private void menuItemRefresh_Click(object sender, EventArgs e) + { + DirectableEncConverter.EncConverters.Reinitialize(); + InitializeConverterList(); + } + + private void listBoxExistingConverters_SelectedIndexChanged(object sender, EventArgs e) { RevaluateButtonState(); } @@ -1338,5 +1362,5 @@ private void right2LeftToolStripMenuItem_Click(object sender, EventArgs e) ToolStripMenuItem aMenuItem = (ToolStripMenuItem)sender; textBoxDataPreview.RightToLeft = (aMenuItem.Checked) ? RightToLeft.Yes : RightToLeft.No; } - } + } } diff --git a/src/EncCnvtrs/SelectConverter.resx b/src/EncCnvtrs/SelectConverter.resx index 90875326..f5d1cf33 100755 --- a/src/EncCnvtrs/SelectConverter.resx +++ b/src/EncCnvtrs/SelectConverter.resx @@ -112,30 +112,33 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + 222, 17 - + 17, 17 - + + 107, 17 + + 335, 17 - - 107, 17 + + 222, 17 - + 473, 17 - + 575, 17 - + AAABAAIAICAQAAAAAADoAgAAJgAAABAQEAAAAAAAKAEAAA4DAAAoAAAAIAAAAEAAAAABAAQAAAAAAIAC diff --git a/src/EncCnvtrs/app.config b/src/EncCnvtrs/app.config index b7b7ec13..cc933720 100755 --- a/src/EncCnvtrs/app.config +++ b/src/EncCnvtrs/app.config @@ -1,7 +1,10 @@ - + +
+ + @@ -13,4 +16,17 @@ + + + + + + {[aeiou]}->{V};1 + {[^aeiou]}->{C};1 + {[\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD]}->{}; + + + + + diff --git a/src/RunTests/Main.cs b/src/RunTests/Main.cs index 036752c7..bffe70e2 100644 --- a/src/RunTests/Main.cs +++ b/src/RunTests/Main.cs @@ -15,6 +15,7 @@ public static void Main (string[] args) RunTestIcuConvEncConverter(); RunTestIcuTranslit(); RunTestIcuRegex(); + RunTestNetRegex(); Console.WriteLine("{0} Tests Run; {1} Tests Failed", m_crun, m_cfail); } @@ -173,5 +174,22 @@ public static void RunTestIcuRegex() catch (Exception e) { Console.WriteLine("Exception caught during TestIcuRegex setup or teardown: {0}", e.Message); } Console.WriteLine("Done Testing IcuRegex"); } + + public static void RunTestNetRegex() + { + Console.WriteLine("Begin Testing NetRegex"); + var test = new TestNetRegex(); + try + { + try { test.TestRegexToVandC(); Console.WriteLine("TestRegexToVandC succeeded!"); } + catch (Exception e) { Console.WriteLine("TestRegexToVandC failed: {0}", e.Message); ++m_cfail; } + ++m_crun; + try { test.TestRegexForNonAnsiRange(); Console.WriteLine("TestRegexForNonAnsiRange succeeded!"); } + catch (Exception e) { Console.WriteLine("TestRegexForNonAnsiRange failed: {0}", e.Message); ++m_cfail; } + ++m_crun; + } + catch (Exception e) { Console.WriteLine("Exception caught during TestNetRegex setup or teardown: {0}", e.Message); } + Console.WriteLine("Done Testing NetRegex"); + } } } diff --git a/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj b/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj index f3ee2072..3bc8c67e 100644 --- a/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj +++ b/src/TestEncCnvtrs/TestEncCnvtrs 2010.csproj @@ -84,6 +84,7 @@ + diff --git a/src/TestEncCnvtrs/TestIcuRegex.cs b/src/TestEncCnvtrs/TestIcuRegex.cs index 75ef26b4..36f00b47 100644 --- a/src/TestEncCnvtrs/TestIcuRegex.cs +++ b/src/TestEncCnvtrs/TestIcuRegex.cs @@ -55,9 +55,10 @@ public void TestRegexForNonAnsiRange() [TestCase("\\u0930->r", "पोथी रथ", "पोथी rथ")] [TestCase("र->r", "पोथी रथ", "पोथी rथ")] // these don't work bkz the C++ side of it (or maybe a bug in ICU, I can't tell) - // doesn't convert, for example, \\u200d to UTF8 properly + // doesn't convert, for example, \\u200d (or …) to UTF8 properly // [TestCase("[\\u200c\\u200d]->", "व्‍यक्‌ति", "व्यक्ति")] // [TestCase("[\\u2020\\u2021\\u200c\\u200d\\u230a\\u230b]->", "⌊व्‍यक्‌ति⌋ † ‡", "व्यक्ति ")] + // [TestCase("(a\uE03C|[⌊⌋\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD])->", "ham… ", "ham… ")] public void TestRegexForUnicodeEscapeCharacters(string converterSpec, string strInput, string strOutput) { var rec = new IcuRegexEncConverter(); diff --git a/src/TestEncCnvtrs/TestNetRegex.cs b/src/TestEncCnvtrs/TestNetRegex.cs new file mode 100644 index 00000000..911bc426 --- /dev/null +++ b/src/TestEncCnvtrs/TestNetRegex.cs @@ -0,0 +1,76 @@ +// created by Steve McConnel, Feb 9, 2012. + +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Text; + +using NUnit.Framework; + +using ECInterfaces; +using SilEncConverters40; + +namespace TestEncCnvtrs +{ + [TestFixture] + public class TestNetRegex + { + [Test] + public void TestRegexToVandC() + { + NetRegexEncConverter rec = new NetRegexEncConverter(); + string lhsEncoding = "UNICODE"; + string rhsEncoding = "UNICODE"; + ConvType convType = ConvType.Unicode_to_from_Unicode; + int procFlags = (int)ProcessTypeFlags.ICURegularExpression; + rec.Initialize("Vowels->V", "{[aeiou]}->{V};1", + ref lhsEncoding, ref rhsEncoding, ref convType, ref procFlags, 0, 0, false); + string output = rec.Convert("abcdEfGhijklMnopqrstUwxyz"); + Assert.AreEqual("VbcdVfGhVjklMnVpqrstVwxyz", output, + "Net regex converter should work properly!"); + // Note this is not case-sensitive, so the capital Vs should remain. + rec.Initialize("Consonants->C", "{[bcdfghjklmnpqrstwxyz]}->{C};1", + ref lhsEncoding, ref rhsEncoding, ref convType, ref procFlags, 0, 0, false); + string output2 = rec.Convert(output); + Assert.AreEqual("VCCCVCCCVCCCCCVCCCCCVCCCC", output2, + "reinitialized Net regex converter should work properly!"); + } + + [Test] + public void TestRegexForNonAnsiRange() + { + NetRegexEncConverter rec = new NetRegexEncConverter(); + string lhsEncoding = "UNICODE"; + string rhsEncoding = "UNICODE"; + ConvType convType = ConvType.Unicode_to_from_Unicode; + int procFlags = (int)ProcessTypeFlags.ICURegularExpression; + rec.Initialize("RemoveDigits", "{\\d}->{}", + ref lhsEncoding, ref rhsEncoding, ref convType, ref procFlags, 0, 0, false); + string output = rec.Convert("पोथी रे ते मियाः 1234567890123456789057 हेनाः"); + Assert.AreEqual("पोथी रे ते मियाः हेनाः", output, + "Net regex converter should work properly for non-latin ranges of unicode also (for which UTF8String won't work on Windows)!"); + } + + [Test] + [TestCase("{[a-e]}->{\u2020};1", "an Apple", "†n †ppl†")] + [TestCase("{\\u0930}->{r}", "पोथी रथ", "पोथी rथ")] + [TestCase("{र}->{r}", "पोथी रथ", "पोथी rथ")] + [TestCase("{[\\u200c\\u200d]}->{}", "व्‍यक्‌ति", "व्यक्ति")] + [TestCase("{[\\u2020\\u2021\\u200c\\u200d\\u230a\\u230b]}->{}", "⌊व्‍यक्‌ति⌋ † ‡", "व्यक्ति ")] + [TestCase("{(a\uE03C|[⌊⌋\u0027\u002a\u2018\u2019\u201c\u201d\u0303\u0304\u0310\u0314\u0325\u200c\u200d\uE03C\uFFFD])}->{}", "ham… ", "ham… ")] + public void TestRegexForUnicodeEscapeCharacters(string converterSpec, string strInput, string strOutput) + { + var rec = new NetRegexEncConverter(); + string lhsEncoding = "UNICODE"; + string rhsEncoding = "UNICODE"; + ConvType convType = ConvType.Unicode_to_from_Unicode; + int procFlags = (int)ProcessTypeFlags.ICURegularExpression; + rec.Initialize("TransliterateDevanagariR", converterSpec, + ref lhsEncoding, ref rhsEncoding, ref convType, ref procFlags, 0, 0, false); + string output = rec.Convert(strInput); + Assert.AreEqual(strOutput, output, + $"Net regex converter should work properly for Unicode Escape sequences (e.g. {converterSpec}) also!"); + } + } +} + From e5b8a3dec546c9f522e5944513dd19474321c0d6 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 22 Nov 2023 14:37:52 -0600 Subject: [PATCH 084/113] fix a bug in the NLLB implementation whereby a long text fragment ending in a fragment w/ no sentence final punctuation would ignore the 'split into sentences' limitation. --- .../NllbTranslatorEncConverter.cs | 13 +++- src/TestEncCnvtrs/TestEcTranslators.cs | 73 ++++++++++++------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs index dde601f1..faa5a8ea 100644 --- a/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs +++ b/src/EcTranslators/NllbTranslator/NllbTranslatorEncConverter.cs @@ -312,6 +312,7 @@ protected string DoConvert(string strInput) if (strInput.StartsWith(SplitSentencesPrefix)) { SetSplitSentences(strInput.Substring(Math.Min(strInput.Length, SplitSentencesPrefix.Length))?.StartsWith("ON") ?? false); + return strInput; } } @@ -324,14 +325,18 @@ protected string DoConvert(string strInput) { var accumulatedSentences = String.Join(String.Empty, sentences.Select(s => s.Sentence)); System.Diagnostics.Debug.Assert(strInput.Contains(accumulatedSentences)); - var addlInput = strInput.Substring(accumulatedSentences.Length); // add the remaining bit that didn't end in a sentence final puntuation + var leftOver = strInput.Substring(accumulatedSentences.Length); // add the remaining bit that didn't end in a sentence final puntuation var lastSentence = sentences.LastOrDefault(); if (lastSentence != default) { - sentences.Remove(lastSentence); // remove it here, so it can be added back combined later - addlInput = lastSentence.Sentence + addlInput; + var addlInput = lastSentence.Sentence + leftOver; + if (WordCount(addlInput) <= MaxTokensPerSentence) + { + sentences.Remove(lastSentence); // remove it here, so it can be added back combined later + leftOver = addlInput; + } } - toAdd = (WordCount(addlInput), addlInput); + toAdd = (WordCount(leftOver), leftOver); } } else diff --git a/src/TestEncCnvtrs/TestEcTranslators.cs b/src/TestEncCnvtrs/TestEcTranslators.cs index 595993cb..22480807 100644 --- a/src/TestEncCnvtrs/TestEcTranslators.cs +++ b/src/TestEncCnvtrs/TestEcTranslators.cs @@ -199,40 +199,61 @@ public void CleanupForClass() m_repoFile = null; } - private const string NllbConverterFriendlyName = "NllbTranslator"; - - /// - /// To run this test, you need to go thru the instructions in have the $(SolutionDir)redist\Help\NLLB_Translate_Plug-in_About_box.htm - /// file to create a docker container for the NLLB 600m model and run it on your local machine. - /// Two additional notes: - /// 1) have no api key in the NLLB Model Config dialog (or set up an env var with it--see TestAzureOpenAiConverter for an eg) - /// 2) Change the @"D:\NLLB\test" path to wherever you chose as the Docker Project folder. - /// - /// ConverterIdentifier of the NLLB converter to be used to convert the text - /// The text to be translated - /// The expected translation - [Test] + private const string NllbConverterFriendlyName = "NllbTranslator"; + + /// + /// To run this test, you need to go thru the instructions in have the $(SolutionDir)redist\Help\NLLB_Translate_Plug-in_About_box.htm + /// file to create a docker container for the NLLB 600m model and run it on your local machine. + /// Two additional notes: + /// 1) have no api key in the NLLB Model Config dialog (or set up an env var with it--see TestAzureOpenAiConverter for an eg) + /// 2) Change the @"D:\NLLB\test" path to wherever you chose as the Docker Project folder. + /// + /// ConverterIdentifier of the NLLB converter to be used to convert the text + /// The text to be translated + /// The expected translation + [Test] [TestCase(@"D:\NLLB\test;hin_Deva;eng_Latn", @"फिर एक स्‍वर्गदूत ने मुझसे कहा, ""इस बात को लिख ले: वे धन्य हैं, जिनको मेमने के विवाह के भोज का निमन्‍त्रण है। यह परमेश्वर के सच्‍चे बोल हैं।", @"Then an angel said to me, ""Write: Blessed are those who are invited to the wedding banquet of the Lamb"". These are the true words of God.")] - [TestCase(@"D:\NLLB\test;hin_Deva;eng_Latn", - "वे जानते हैं कि परमेश्वर का अस्तित्व है और यह सब कुछ उनके लिए ही बनाया है। परंतु फिर भी न तो वे परमेश्वर का कोई सम्‍मान, और न ही तो उसका धन्यवाद करते हैं। इसलिए उनकी आँखें में पर्दा पड़ गया है, और परमेश्वर के विषय में उनका जो विचार है, वह गलत हो चुका है।", - "They know that God exists and that everything was made for them. Yet they do not give glory to God or give him thanks. Their minds are blinded and their thoughts are in error.")] - public void TestNllbConverter(string converterSpec, string testInput, string testOutput) - { - m_encConverters.AddConversionMap(NllbConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, - EncConverters.strTypeSILNllbTranslator, "UNICODE", "UNICODE", ProcessTypeFlags.Translation); + [TestCase(@"D:\NLLB\nllb-600m;hin_Deva;eng_Latn;http://localhost:8000;N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1", + "वे जानते हैं कि परमेश्वर का अस्तित्व है और यह सब कुछ उनके लिए ही बनाया है। परंतु फिर भी न तो वे परमेश्वर का कोई सम्‍मान, और न ही तो उसका धन्यवाद करते हैं। इसलिए उनकी आँखें में पर्दा पड़ गया है, और परमेश्वर के विषय में उनका जो विचार है, वह गलत हो चुका है।", + "They know that God exists and that everything was made for them. Yet they do not give glory to God or give him thanks. Their minds are blinded and their thoughts are in error.")] + [TestCase(@"D:\NLLB\nllb-600m;hin_Deva;eng_Latn;http://localhost:8000;N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1", + "(केवल ये शहीद और न्याय करने वाले लोग हजार वर्षों वाले उस युग के आरंभ में पुनर्जीवित हो जाएँगे। इस बार जीवित होने को “पहला जीवित होना” कहते हैं। बाकि जो मरे हुए हैं, परमेश्वर उन सबको तब तक पुनर्जीवित नहीं करेगा, जब तक उस हजार वर्षों वाले युग का अंत नहीं होगा।)", + "(The only resurrection will be the ones who died and judged at the beginning of the thousand years. This resurrection is called the First Resurrection. The rest of the dead God did not raise until the thousand years were over.)")] + [TestCase(@"D:\NLLB\nllb-600m;hin_Deva;eng_Latn;http://localhost:8000;N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1", + "केवल ये शहीद और न्याय करने वाले लोग हजार वर्षों वाले उस युग के आरंभ में पुनर्जीवित हो जाएँगे। इस बार जीवित होने को “पहला जीवित होना” कहते हैं। बाकि जो मरे हुए हैं, परमेश्वर उन सबको तब तक पुनर्जीवित नहीं करेगा, जब तक उस हजार वर्षों वाले युग का अंत नहीं होगा,", + "Only these martyrs and judges will be resurrected at the beginning of that millennial age. This time the resurrection is called the First Resurrection. The rest of the dead God did not raise until the thousand years were over.")] + [TestCase(@"D:\NLLB\nllb-600m;hin_Deva;eng_Latn;http://localhost:8000;N3RK/o+wYtvEFMVGtYsmROIyLr/+RWh1", + "बाकि जो मरे हुए हैं, परमेश्वर उन सबको तब तक पुनर्जीवित नहीं करेगा, जब तक उस हजार वर्षों वाले युग का अंत नहीं होगा,", + "The rest of the dead God did not raise until the thousand years were over.")] // yes, NLLB changes the final ',' to a '.' + public void TestNllbConverter(string converterSpec, string testInput, string testOutput) + { + m_encConverters.AddConversionMap(NllbConverterFriendlyName, converterSpec, ConvType.Unicode_to_Unicode, + EncConverters.strTypeSILNllbTranslator, "UNICODE", "UNICODE", ProcessTypeFlags.Translation); + + var theEc = m_encConverters[NllbConverterFriendlyName]; - var theEc = m_encConverters[NllbConverterFriendlyName]; + // do a forward conversion + var strOutput = theEc.Convert(testInput); + if (testOutput != strOutput) + { + // if you do the same conversion a 3rd time, then it will limit the token count and process the text is sentence chunks + strOutput = theEc.Convert(testInput); + strOutput = theEc.Convert(testInput); - // do a forward conversion - var strOutput = theEc.Convert(testInput); - Assert.AreEqual(testOutput, strOutput); - } + // OR you can do this: + theEc.Convert(NllbTranslatorEncConverter.SplitSentencesPrefix + "ON"); + strOutput = theEc.Convert(testInput); + } + + Assert.AreEqual(testOutput, strOutput); + theEc.Convert(NllbTranslatorEncConverter.SplitSentencesPrefix + "OFF"); // to turn it off for the next run + } - private const string AzureOpenAIConverterFriendlyName = "ChatGptTranslator"; + private const string AzureOpenAIConverterFriendlyName = "ChatGptTranslator"; [Test] [TestCase("Hindi;English;Translate from Hindi into English.", "यीशु ने यह भी कहा,", "Jesus also said this,")] From 3fd86c41c5f7c4e232dc27518f1e713272824477 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Wed, 22 Nov 2023 14:38:29 -0600 Subject: [PATCH 085/113] changed the default Python for the Python3 testing to 3.9 (the version I have to have for use with my AI language model work). --- src/TestEncCnvtrs/TestPy3ScriptEncConverters.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/TestEncCnvtrs/TestPy3ScriptEncConverters.cs b/src/TestEncCnvtrs/TestPy3ScriptEncConverters.cs index c9d25374..c4d4a09e 100644 --- a/src/TestEncCnvtrs/TestPy3ScriptEncConverters.cs +++ b/src/TestEncCnvtrs/TestPy3ScriptEncConverters.cs @@ -28,9 +28,9 @@ public class TestPy3ScriptEncConverters bool m_fSetRegistryValue; string m_repoFile; - // best if you use these as the install path for the two flavors of 3.12 Python for these tests - private const string PathPython64 = @"D:\Python\Python312"; - private const string PathPython86 = @"D:\Python\Python312-32"; + // best if you use these as the install path for the two flavors of 3.9 Python for these tests + private const string PathPython64 = @"D:\Python\Python39"; + private const string PathPython86 = @"D:\Python\Python39-32"; private const string EnvironmentVariableNamePythonHome = "PYTHONHOME"; @@ -224,8 +224,8 @@ public void CleanupForClass() } /// - /// This is a test for Python 3 via the Py3ScriptEncConverter and requires a Python 3.12 to be installed in the D:\Python\Python312 folder - /// So that the file, D:\Python\Python312\python312.dll will exist + /// This is a test for Python 3 via the Py3ScriptEncConverter and requires a Python 3.9 to be installed in the D:\Python\Python39 folder + /// So that the file, D:\Python\Python39\python39.dll will exist /// Note that unless someone complains, this transducer will only support Unicode encoding /// [Test] @@ -233,7 +233,7 @@ public void TestPy3ScriptEncConverter() { var converterName = "UnitTesting-Python3-ReverseString-Unicode"; var dir = Path.Combine(TestEncConverters.GetMapsTablesFolder(), "PythonExamples"); - var converterIdentifierForPython3 = @$"{Path.Combine(dir, "ReverseString.py")};{m_testPythonHome}\python312.dll"; + var converterIdentifierForPython3 = @$"{Path.Combine(dir, "ReverseString.py")};{m_testPythonHome}\python39.dll"; m_encConverters.AddConversionMap(converterName, converterIdentifierForPython3, ConvType.Unicode_to_from_Unicode, EncConverters.strTypeSILPy3Script, "UNICODE", "UNICODE", ProcessTypeFlags.PythonScript); From 87c3e21ce3cf21024cc73608ad36654bc1e46951 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sun, 3 Dec 2023 10:03:28 +0530 Subject: [PATCH 086/113] GHA to build the nuget package choses the wrong version of several packages (despite what's in the app.config and the *.csproj), which causes an install time problem. --- .../AzureOpenAi/AzureOpenAiExe/Program.cs | 120 ++++++++++-------- src/EcTranslators/EcTranslators.csproj | 21 +++ 2 files changed, 87 insertions(+), 54 deletions(-) diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs index 4d754fd4..dcc8bbef 100644 --- a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs @@ -26,64 +26,76 @@ internal class Program private static readonly char[] TrimmableChars = new char[] { '\r', '\n', ' ' }; static async Task Main(string[] args) - { - // set the stdin/out to Unicode - Console.InputEncoding = Encoding.Unicode; - Console.OutputEncoding = Encoding.Unicode; - - if (!IsValidParameters(args, out string deploymentName, out string endpoint, out string key, out string systemPrompt)) - return; - - // Pass the deployment name you chose when you created/deployed the model in Azure OpenAI Studio. - var client = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(key)); - - // create the ChatMessages w/ the given systemPrompt - var chatMessages = new List - { - new ChatMessage(ChatRole.System, systemPrompt) - }; - var chatCompletionOptions = new ChatCompletionsOptions(chatMessages); - - // in case there are multiple lines (e.g. what Paratext will do if the verse has multiple paragraphs), - // process in a while loop - var index = 0; - List input = null; // new List { "वहाँ वह विश्राम के दिन प्रार्थना घर में जाकर लोगों को परमेश्वर का वचन सुनाने लगा। सब लोग सुनकर चकित हो गये।", "", "परंतु कई तो यह भी कहने लगे, “यह ज्ञान इसको कहाँ से आया!? और ऐसे सामर्थ्‍य के काम यह कैसे करता है, जिसकी चर्चा सब लोग कर रहे हैं!?" }; - while ((input != null && input.Count > index) || (input == null && Console.In.Peek() != -1)) - { - var strInput = (input != null) - ? input[index++] - : Console.ReadLine(); - if (String.IsNullOrEmpty(strInput?.Trim(TrimmableChars))) // don't actually trim them, but just for the sake of finding nothing to translate... - continue; - - // add the string to be translated to as the 'user' message - chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.User, strInput)); - - // call the service to process the user msg based on the given system prompt - var chatCompletions = await client.GetChatCompletionsAsync(deploymentName, chatCompletionOptions); - - // clean up and return the "assistent's response" - var strOutput = HarvestResult(strInput, chatCompletions.Value.Choices[0]); - - // put that back in the chat, in case we are processing multiple lines - // (this'll make them 'related' for better translation) - chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.Assistant, strOutput)); - } - - for (var i = 1; i < chatCompletionOptions.Messages.Count;) - { - var strInput = chatCompletionOptions.Messages[i++].Content; - var strOutput = chatCompletionOptions.Messages[i++].Content; + { + // set the stdin/out to Unicode + Console.InputEncoding = Encoding.Unicode; + Console.OutputEncoding = Encoding.Unicode; + + if (!IsValidParameters(args, out string deploymentName, out string endpoint, out string key, out string systemPrompt)) + return; + + try + { + await ProcessRequest(deploymentName, endpoint, key, systemPrompt); + } + catch (Exception ex) + { + System.Diagnostics.Debug.Fail(ex.Message); + } + } + + private static async Task ProcessRequest(string deploymentName, string endpoint, string key, string systemPrompt) + { + // Pass the deployment name you chose when you created/deployed the model in Azure OpenAI Studio. + var client = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(key)); + + // create the ChatMessages w/ the given systemPrompt + var chatMessages = new List + { + new ChatMessage(ChatRole.System, systemPrompt) + }; + var chatCompletionOptions = new ChatCompletionsOptions(chatMessages); + + // in case there are multiple lines (e.g. what Paratext will do if the verse has multiple paragraphs), + // process in a while loop + var index = 0; + List input = null; // new List { "वहाँ वह विश्राम के दिन प्रार्थना घर में जाकर लोगों को परमेश्वर का वचन सुनाने लगा। सब लोग सुनकर चकित हो गये।", "", "परंतु कई तो यह भी कहने लगे, “यह ज्ञान इसको कहाँ से आया!? और ऐसे सामर्थ्‍य के काम यह कैसे करता है, जिसकी चर्चा सब लोग कर रहे हैं!?" }; + while ((input != null && input.Count > index) || (input == null && Console.In.Peek() != -1)) + { + var strInput = (input != null) + ? input[index++] + : Console.ReadLine(); + if (String.IsNullOrEmpty(strInput?.Trim(TrimmableChars))) // don't actually trim them, but just for the sake of finding nothing to translate... + continue; + + // add the string to be translated to as the 'user' message + chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.User, strInput)); + + // call the service to process the user msg based on the given system prompt + var chatCompletions = await client.GetChatCompletionsAsync(deploymentName, chatCompletionOptions); + + // clean up and return the "assistent's response" + var strOutput = HarvestResult(strInput, chatCompletions.Value.Choices[0]); + + // put that back in the chat, in case we are processing multiple lines + // (this'll make them 'related' for better translation) + chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.Assistant, strOutput)); + } + + for (var i = 1; i < chatCompletionOptions.Messages.Count;) + { + var strInput = chatCompletionOptions.Messages[i++].Content; + var strOutput = chatCompletionOptions.Messages[i++].Content; #if LogResults - File.AppendAllText(LogFilePath, string.Format("{1}=>{2}:{3}=>{4}{0}", Environment.NewLine, systemPrompt, i / 2, strInput, strOutput)); + File.AppendAllText(LogFilePath, string.Format("{1}=>{2}:{3}=>{4}{0}", Environment.NewLine, systemPrompt, i / 2, strInput, strOutput)); #endif - // write the responses to the standard out to return it - Console.WriteLine(strOutput); - } - } + // write the responses to the standard out to return it + Console.WriteLine(strOutput); + } + } - private static bool IsValidParameters(string[] args, out string deploymentName, out string endpoint, out string key, out string systemPrompt) + private static bool IsValidParameters(string[] args, out string deploymentName, out string endpoint, out string key, out string systemPrompt) { if (args.Length != 4) { diff --git a/src/EcTranslators/EcTranslators.csproj b/src/EcTranslators/EcTranslators.csproj index 1a4d3497..f5be9094 100644 --- a/src/EcTranslators/EcTranslators.csproj +++ b/src/EcTranslators/EcTranslators.csproj @@ -253,6 +253,24 @@ + + 4.4.0 + + + 4.4.0 + + + 1.62.1 + + + 1.62.1 + + + 1.62.1 + + + 1.62.0.875 + 3.2.0 @@ -271,6 +289,9 @@ 6.0.0-preview.4.21253.7 + + 7.0.2 + 4.5.5 From 03393fe054464b13fb91cd731b809bfccad21c52 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sun, 3 Dec 2023 11:01:59 +0530 Subject: [PATCH 087/113] update the nuget package... --- Package.Release.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.Release.nuspec b/Package.Release.nuspec index 38f29e71..baf4489f 100644 --- a/Package.Release.nuspec +++ b/Package.Release.nuspec @@ -2,7 +2,7 @@ Encoding-Converters-Core - 0.8.0 + 0.8.1 Bob Eaton, Jim Kornelson, SIL International jnaylor, sillsdev MIT From 75809be2f67c41af86ac810136f4725dceb20811 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sat, 17 Feb 2024 08:11:38 +0530 Subject: [PATCH 088/113] added support for VertexAI and Prompt based translators (which support posting examples to -- think poor man's fine tuning) and passing parameters to the ExeEncConverter based AzureOpenAI and VertextAi exes as encrypted json (since the command line args are getting complicated) --- EncConverters 2019.sln | 15 + .../EcTranslators_MergeModule.wxs | 129 + .../EcTranslators_MergeModule.wxs | 128 + .../Translators 4.0.0.0 Plugin Details.xml | 6 + .../Vertex_AI_Translate_Plug-in_About_box.htm | 2084 +++++++++++++++++ .../colorschememapping.xml | 2 + .../filelist.xml | 15 + .../header.htm | 61 + .../image001.jpg | Bin 0 -> 21145 bytes .../image001.png | Bin 0 -> 37952 bytes .../image002.jpg | Bin 0 -> 26190 bytes .../image003.jpg | Bin 0 -> 19190 bytes .../image004.jpg | Bin 0 -> 43759 bytes .../image005.jpg | Bin 0 -> 26532 bytes .../image005.png | Bin 0 -> 34103 bytes .../image006.jpg | Bin 0 -> 22764 bytes .../image007.jpg | Bin 0 -> 22764 bytes .../image008.jpg | Bin 0 -> 36769 bytes .../image009.png | Bin 0 -> 79257 bytes .../image010.jpg | Bin 0 -> 36769 bytes .../image011.png | Bin 0 -> 6834 bytes .../image012.jpg | Bin 0 -> 10127 bytes .../image013.jpg | Bin 0 -> 10127 bytes .../image014.png | Bin 0 -> 24854 bytes .../image015.jpg | Bin 0 -> 36388 bytes .../image017.jpg | Bin 0 -> 22096 bytes .../item0013.xml | 1 + .../item0016.xml | 1 + .../item0017.xml | 1 + .../item0018.xml | 1 + .../props014.xml | 2 + .../props017.xml | 2 + .../props018.xml | 2 + .../props019.xml | 2 + .../themedata.thmx | Bin 0 -> 3339 bytes .../AzureOpenAi/AzureOpenAiEncConverter.cs | 38 +- .../AzureOpenAi/AzureOpenAiExe/App.config | 18 +- .../AzureOpenAiExe/AzureOpenAiExe.csproj | 46 +- .../AzureOpenAi/AzureOpenAiExe/Program.cs | 83 +- .../AzureOpenAiExe/packages.config | 16 +- ...penAiPromptExeTranslatorCommandLineArgs.cs | 21 + src/EcTranslators/EcTranslators.csproj | 44 +- .../PromptExeTranslatorCommandLineArgs.cs | 43 + src/EcTranslators/PromptTranslator.cs | 41 + .../Properties/Resources.Designer.cs | 99 +- src/EcTranslators/Properties/Resources.resx | 30 + .../Properties/Settings.Designer.cs | 74 +- .../Properties/Settings.settings | 18 + src/EcTranslators/TranslatorConverter.cs | 2 +- .../QueryForGoogleCredentials.Designer.cs | 148 ++ .../VertexAi/QueryForGoogleCredentials.cs | 41 + .../VertexAi/QueryForGoogleCredentials.resx | 120 + .../VertexAi/VertexAiAutoConfigDialog.cs | 315 +++ .../VertexAiAutoConfigDialog.designer.cs | 322 +++ .../VertexAi/VertexAiAutoConfigDialog.resx | 129 + .../VertexAi/VertexAiEncConverter.cs | 252 ++ .../VertexAi/VertexAiEncConverterConfig.cs | 65 + .../VertexAi/VertexAiExe/App.config | 78 + .../VertexAi/VertexAiExe/MessageClasses.cs | 43 + .../VertexAi/VertexAiExe/Program.cs | 342 +++ .../VertexAiExe/Properties/AssemblyInfo.cs | 36 + .../VertexAi/VertexAiExe/VertexAiExe.csproj | 238 ++ .../VertexAi/VertexAiExe/packages.config | 33 + .../protos/google/api/annotations.proto | 31 + .../VertexAiExe/protos/google/api/auth.proto | 237 ++ .../protos/google/api/backend.proto | 185 ++ .../protos/google/api/billing.proto | 77 + .../protos/google/api/client.proto | 394 ++++ .../protos/google/api/config_change.proto | 84 + .../protos/google/api/consumer.proto | 82 + .../protos/google/api/context.proto | 90 + .../protos/google/api/control.proto | 41 + .../protos/google/api/distribution.proto | 213 ++ .../protos/google/api/documentation.proto | 168 ++ .../protos/google/api/endpoint.proto | 73 + .../protos/google/api/error_reason.proto | 570 +++++ .../protos/google/api/field_behavior.proto | 104 + .../protos/google/api/field_info.proto | 79 + .../VertexAiExe/protos/google/api/http.proto | 379 +++ .../protos/google/api/httpbody.proto | 81 + .../VertexAiExe/protos/google/api/label.proto | 48 + .../protos/google/api/launch_stage.proto | 72 + .../VertexAiExe/protos/google/api/log.proto | 54 + .../protos/google/api/logging.proto | 81 + .../protos/google/api/metric.proto | 268 +++ .../google/api/monitored_resource.proto | 130 + .../protos/google/api/monitoring.proto | 107 + .../protos/google/api/policy.proto | 85 + .../VertexAiExe/protos/google/api/quota.proto | 184 ++ .../protos/google/api/resource.proto | 238 ++ .../protos/google/api/routing.proto | 461 ++++ .../protos/google/api/service.proto | 191 ++ .../protos/google/api/source_info.proto | 31 + .../protos/google/api/system_parameter.proto | 96 + .../VertexAiExe/protos/google/api/usage.proto | 96 + .../protos/google/api/visibility.proto | 113 + .../VertexAiExe/protos/google/rpc/code.proto | 186 ++ .../rpc/context/attribute_context.proto | 344 +++ .../google/rpc/context/audit_context.proto | 49 + .../protos/google/rpc/error_details.proto | 285 +++ .../VertexAiExe/protos/google/rpc/http.proto | 64 + .../protos/google/rpc/status.proto | 49 + .../protos/google/type/calendar_period.proto | 56 + .../protos/google/type/color.proto | 174 ++ .../VertexAiExe/protos/google/type/date.proto | 52 + .../protos/google/type/datetime.proto | 104 + .../protos/google/type/dayofweek.proto | 50 + .../protos/google/type/decimal.proto | 95 + .../VertexAiExe/protos/google/type/expr.proto | 73 + .../protos/google/type/fraction.proto | 33 + .../protos/google/type/interval.proto | 46 + .../protos/google/type/latlng.proto | 37 + .../protos/google/type/localized_text.proto | 36 + .../protos/google/type/money.proto | 42 + .../protos/google/type/month.proto | 65 + .../protos/google/type/phone_number.proto | 113 + .../protos/google/type/postal_address.proto | 134 ++ .../protos/google/type/quaternion.proto | 94 + .../protos/google/type/timeofday.proto | 44 + ...texAiPromptExeTranslatorCommandLineArgs.cs | 17 + src/EcTranslators/app.config | 40 +- src/EncCnvtrs/EncConverters.cs | 2 +- 122 files changed, 12516 insertions(+), 98 deletions(-) create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box.htm create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/colorschememapping.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/filelist.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/header.htm create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image001.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image001.png create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image002.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image003.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image004.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image005.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image005.png create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image006.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image007.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image008.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image009.png create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image010.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image011.png create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image012.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image013.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image014.png create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image015.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image017.jpg create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0013.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0016.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0017.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0018.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props014.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props017.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props018.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props019.xml create mode 100644 redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/themedata.thmx create mode 100644 src/EcTranslators/AzureOpenAi/AzureOpenAiPromptExeTranslatorCommandLineArgs.cs create mode 100644 src/EcTranslators/PromptExeTranslatorCommandLineArgs.cs create mode 100644 src/EcTranslators/PromptTranslator.cs create mode 100644 src/EcTranslators/VertexAi/QueryForGoogleCredentials.Designer.cs create mode 100644 src/EcTranslators/VertexAi/QueryForGoogleCredentials.cs create mode 100644 src/EcTranslators/VertexAi/QueryForGoogleCredentials.resx create mode 100644 src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.cs create mode 100644 src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.designer.cs create mode 100644 src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.resx create mode 100644 src/EcTranslators/VertexAi/VertexAiEncConverter.cs create mode 100644 src/EcTranslators/VertexAi/VertexAiEncConverterConfig.cs create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/App.config create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/MessageClasses.cs create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/Program.cs create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/Properties/AssemblyInfo.cs create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/VertexAiExe.csproj create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/packages.config create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/annotations.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/auth.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/backend.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/billing.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/client.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/config_change.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/consumer.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/context.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/control.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/distribution.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/documentation.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/endpoint.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/error_reason.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_behavior.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_info.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/http.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/httpbody.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/label.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/launch_stage.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/log.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/logging.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/metric.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitored_resource.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitoring.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/policy.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/quota.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/resource.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/routing.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/service.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/source_info.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/system_parameter.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/usage.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/visibility.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/code.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/attribute_context.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/audit_context.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/error_details.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/http.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/status.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/calendar_period.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/color.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/date.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/datetime.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/dayofweek.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/decimal.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/expr.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/fraction.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/interval.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/latlng.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/localized_text.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/money.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/month.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/phone_number.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/postal_address.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/quaternion.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/timeofday.proto create mode 100644 src/EcTranslators/VertexAi/VertexAiPromptExeTranslatorCommandLineArgs.cs diff --git a/EncConverters 2019.sln b/EncConverters 2019.sln index 41dc7962..3c3962dd 100644 --- a/EncConverters 2019.sln +++ b/EncConverters 2019.sln @@ -43,6 +43,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SilIndicEncConverters 2010" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ECDriver", "src\ECDriver\windows\ECDriver 2010.vcxproj", "{1AE110F1-E97B-4D14-9F3A-8AF01344E3B9}" ProjectSection(ProjectDependencies) = postProject + {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6} = {1E45DBF2-3629-4413-AC1F-61E6AA33B9B6} {2935E02F-43ED-4670-9A00-A91B0AD3D66C} = {2935E02F-43ED-4670-9A00-A91B0AD3D66C} {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} = {3E4B908A-4F96-43C5-981B-1AA4B73CCC26} EndProjectSection @@ -206,6 +207,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackTranslationHelper", "sr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureOpenAiExe", "src\EcTranslators\AzureOpenAi\AzureOpenAiExe\AzureOpenAiExe.csproj", "{4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VertexAiExe", "src\EcTranslators\VertexAi\VertexAiExe\VertexAiExe.csproj", "{5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -636,6 +639,18 @@ Global {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Template|Win32.Build.0 = Debug|x86 {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Template|x64.ActiveCfg = Debug|x64 {4F6FF8AD-6BEB-4104-B123-7FA9C2DC0BBE}.Template|x64.Build.0 = Debug|x64 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Debug|Win32.ActiveCfg = Debug|x86 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Debug|Win32.Build.0 = Debug|x86 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Debug|x64.ActiveCfg = Debug|x64 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Debug|x64.Build.0 = Debug|x64 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Release|Win32.ActiveCfg = Release|x86 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Release|Win32.Build.0 = Release|x86 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Release|x64.ActiveCfg = Release|x64 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Release|x64.Build.0 = Release|x64 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Template|Win32.ActiveCfg = Debug|Any CPU + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Template|Win32.Build.0 = Debug|Any CPU + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Template|x64.ActiveCfg = Debug|Any CPU + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982}.Template|x64.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs b/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs index 230401c9..d29a4679 100644 --- a/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs +++ b/installer/EcTranslators64bitMM/EcTranslators_MergeModule.wxs @@ -25,6 +25,9 @@ + + + @@ -41,6 +44,9 @@ + + + @@ -145,6 +151,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -169,6 +195,9 @@ + + + @@ -384,6 +413,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -512,6 +619,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs b/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs index 2efff3f9..3c16dd91 100644 --- a/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs +++ b/installer/EcTranslatorsMM/EcTranslators_MergeModule.wxs @@ -24,6 +24,9 @@ + + + @@ -40,6 +43,9 @@ + + + @@ -144,6 +150,25 @@ + + + + + + + + + + + + + + + + + + + @@ -169,6 +194,9 @@ + + + @@ -384,6 +412,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -512,6 +618,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml b/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml index 42766727..35aedd03 100644 --- a/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml +++ b/redist/EC/Plugins/Translators 4.0.0.0 Plugin Details.xml @@ -30,4 +30,10 @@ DisplayName="Azure OpenAI Translator" ConfiguratorProgId="SilEncConverters40.EcTranslators.AzureOpenAI.AzureOpenAiEncConverterConfig" AssemblyReference="EcTranslators, Version=4.0.0.0, Culture=neutral, PublicKeyToken=f1447bae1e63f485" /> + diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box.htm b/redist/Help/Vertex_AI_Translate_Plug-in_About_box.htm new file mode 100644 index 00000000..16bff516 --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box.htm @@ -0,0 +1,2084 @@ + + + + + + + + + + + +Vertex AI Translate + + + + + + + + + + + +
+ +

Vertex AI Transducer

+ +

This +converter allows you to use Vertex AI +to do text processing within EncConverter-enabled applications. Vertex AI +is a cloud-based Artificial Intelligence service offered in Google Cloud with a +number of Translation-related generative AI models, such as PaLM API, Llama 2, and the Gemini Pro models in their Model Garden.

+ +

In +the EncConverters domain, this transducer can be used to do translation between +languages supported by the model (see this website for specific languages supported). Note that +it requires a live internet connection to function.

+ +

The +Vertex AI Transducer uses an Vertex AI Resource to do the translation, +which is available from Google’s portal, and unlike other +Translators supported by the EncConverters core (i.e. Google, Bing & +DeepL), the Vertex AI Resource requires you to get your own Vertex AI resource +in order to use it.

+ +

See +this website for more information on getting your own +Vertex AI Resource.

+ +

Setup Tab

+ +

Here is the configuration setup tab for the Vertex AI +EncConverter:

+ +

+ +

Figure 1: +Vertex AI Translate Setup 1, 2, +3, 4, 5, +6, 7, 8, 9, 10, +11

+ +

 

+ +

1)      +This text box is for entering the Google +Cloud Project ID in which you have a Vertex AI resource. See Google Cloud help +for help.

+ +

2)      This text box is for entering the Location Id +of your Vertex AI resource. See Google Cloud help +for instructions on creating a Vertex AI resource.

+ +

3)      This +text box is for entering the Publisher of your Vertex AI resource. (e.g. for a chat-bison AI resource, the publisher is google.

+ +

4)      This +text box is for entering the Model Id of your Vertex AI resource. (e.g. chat-bison, chat-bison-32k, +or gemini-pro).

+ +

5)      +This text box is for entering +the Source language of the input text for the translation operation.

+ +

6)      +This text box is for entering +the Target language the input text should be translated into.

+ +

7)      This combo box/text box is for choosing one +of the pre-existing additions or entering your own addition to be added to the System +Prompt to customize what is sent to the Vertex AI service.

+ +

In the example shown +above, the addition tells the AI language model to translate from Hindi to +English and request the result be “in a ‘free translation’ +style.”

+ +

The underlying language +model is quite good at understanding English and can adjust its translation for +most requests (e.g. even sending the results back in rhyme or in ‘Yoda +speak’ (OSV))

+ +

Click on the drop-down +arrow to the right of the box to see any pre-loaded or previously used +additions.

+ +

By default, the System +Prompt used is:

+ +

You are a Language Translator +that Translates between different languages. Your job is to translate the text +in the user prompt into the requested language according to the following +instructions: You will be given 1 or more lines of text in <SourceLanguage> +which you are to translate into <TargetLanguage> <additions> and +return only the translated lines.

+ +

This prompt was picked +to allow the converter to work well with the Paratext Back Translation plug-in, +which often has multiple lines (i.e. verses) of text to be processed and as the +language model often returns additional information about the input line to be +translated, by default, it is instructed to return only the translated text.

+ +

You can override this +formatted System Prompt to get any arbitrary results you want by using the +prefix: “UseSystemPrompt: ”

+ +

For example, to see if +it meets the needs of your application, you could start with the simple System +Prompt (which, since the Resource charges by the number of word token used +would result in a lower overall cost):

+ +

UseSystemPrompt: Translate +Hindi into English.

+ +

Then, the System Prompt +sent to the language model would simply be:

+ +

Translate Hindi into English.

+ +

Note that if you begin +this field with the string, “UseSystemPrompt: ”, then the Source +and Target language boxes will be ignored.

+ +

Finally, you should +note that the Vertex AI Resource has Content Filtering +and it may refuse to translate some text if it runs afoul of any of these four +areas: Violent, Harmful, Sexually explicit, Hate speech, Harassment, +Dangerous or Toxic.

+ +

8)      +This box shows the System Prompt that will be sent to +the Vertex AI service.

+ +

9)      +This +button brings up a dialog box into which you can enter the information needed +about your personal Google Cloud Account Credentials (see below for +information).

+ +

Note that unlike the +other Translators supported by EncConverters, the Vertex AI (currently) does +not have a free pricing tier, and so you must get your own resource to use it.

+ +

See this +webpage for how to get your own Vertex AI resource to use for this transducer.

+ +

10)  If you want the +converter to be permanently added to the System Repository, then you must click +the Save in System Repository button +(see below).

+ +

11)  You +can click on the Test Area tab to test the converter with some sample data.

+ +
+ +

You may not see script errors until you use the converter to +convert some data. So, for this converter type, it is important to test it +before trying it with real data.

+ +

You can also test various System Prompts in the Vertex AI +Studio mentioned below to find the specific one you want to use.

+ +
+ +

Entering your own Google Cloud Credentials

+ +

Once you acquire your own Vertex AI resource on the Google +Cloud portal, +you can enter the credentials (as json) to use it in the dialog that appears by +clicking the button on the Setup dialog (9)  above:

+ +

 

+ +

+ +

Figure 2: Entering +Vertex AI Credentials

+ +

 

+ +

The information you need for this dialog is available, +after you have created your Vertex AI Service Account, by click the APIs & +Services blade in the Google Cloud Console:

+ +

+ +

Figure 3: Google Cloud +Console to Create Credentials for Vertex AI Resource

+ +

 

+ +

From this credentials page, you can create a new +credentials (json) key that you will want to save in a safe place. Note that +the credentials are stored encrypted in the settings files of each application +it’s used in, and so you may need to enter the credentials multiple +times, once for each client application (e.g. Paratext +or Word, etc.)

+ +

+ +

Figure 4: Google Cloud +Console Service Account Credentials Page

+ +

 

+ +

Saving the +converter in the System Repository:

+ +

By default, if you click the Apply or OK +buttons, the configured converter will be returned to the client application as +a temporary converter for temporary use. Once the client application (e.g. Paratext or Word) is +closed or releases the converter, it will no longer be available. If you want +the converter to be permanently available to client applications, then you must +explicitly add it to the System Repository using +the Save in System Repository button.

+ +

When you click this button, the following dialog box will +be displayed to query for a friendly name by +which the converter will be known in client applications:

+ +

 

+ +

+ +

 

+ +

The Advanced Tab can be used to enter further, +optional information about this converter, which is also put into the System Repository and can be used by various client +applications. Click on this tab to display the following dialog box:

+ +

+ +

 

+ +

Though these values are not necessary for the operation of +the converter, they can be helpful to various client applications. For example, +the Clipboard EncConverter can be configured to filter +the list of displayed converters based on the Encoding Name and/or the Transduction +Type configured here.

+ +
+ + + + diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/colorschememapping.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/colorschememapping.xml new file mode 100644 index 00000000..6a0069cd --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/colorschememapping.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/filelist.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/filelist.xml new file mode 100644 index 00000000..998a0a0e --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/filelist.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/header.htm b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/header.htm new file mode 100644 index 00000000..eb2550fe --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/header.htm @@ -0,0 +1,61 @@ + + + + + + + + + + + + + +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ +
+ +

+ +


+ +

+ +
+ + + + diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image001.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image001.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8a85e291e9ca5ddeb88c89535e932ed9765eff58 GIT binary patch literal 21145 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 h+Ur%zqB7MA`q}1OR|a`@#SK literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image001.png b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image001.png new file mode 100644 index 0000000000000000000000000000000000000000..7507850ad85523b4db554fbd1801934d8b2ab0af GIT binary patch literal 37952 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

EkLhC41;Y1Tn;OYDsFBl9eJZF0gExTjJ{ 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image002.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a8c2ada194d473e9f833e937568e82817a28c98d GIT binary patch literal 26190 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%0AZkPPFw9#E6U(}M&YBlljBPTt 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image004.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..786259718006cd137bfc028ddcd196d38cc86b4b GIT binary patch literal 43759 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image005.png b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image005.png new file mode 100644 index 0000000000000000000000000000000000000000..994ac3cee8d88005d8f259a206cc627710a40b4e GIT binary patch literal 34103 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�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 Z4p?!R(!RnPSOEe4NlVC!*NGYi{~z)X56b`m literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image006.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image006.jpg new file mode 100644 index 0000000000000000000000000000000000000000..377433592c01a24297d4e67c9b2d5808b75e9751 GIT binary patch literal 22764 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 IL;e4o0Gaeup#T5? literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image007.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image007.jpg new file mode 100644 index 0000000000000000000000000000000000000000..377433592c01a24297d4e67c9b2d5808b75e9751 GIT binary patch literal 22764 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 IL;e4o0Gaeup#T5? literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image008.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image008.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df2f96f588fa7267cf0a26c48851e25b8e86ba5b GIT binary patch literal 36769 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image009.png b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image009.png new file mode 100644 index 0000000000000000000000000000000000000000..10e5ff1f8187c588fd3dbbf3ebc98a3430452af1 GIT binary patch literal 79257 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 /// The class constructor. public AzureOpenAiEncConverter() - : base( - typeof(AzureOpenAiEncConverter).FullName, - ImplTypeSilAzureOpenAi, - ConvType.Unicode_to_Unicode, // conversionType - EncConverters.strDefUnicodeEncoding, // lhsEncodingID - EncConverters.strDefUnicodeEncoding, // rhsEncodingID - (Int32)ProcessTypeFlags.Translation, // lProcessType - "") + : base + ( + typeof(AzureOpenAiEncConverter).FullName, + ImplTypeSilAzureOpenAi + ) { } @@ -215,9 +212,22 @@ public override string Arguments EncConverters.cstrCaption); } - // The system prompt can't have double quotes in it, bkz those are used for separating the 4 command line parameters, - // So convert them to single quotes, which should also work - return $"\"{azureOpenAiDeploymentName}\" \"{azureOpenAiEndpoint}\" \"{azureOpenAiKey}\" \"{AiSystemInstructions.Replace("\"", "'")}\""; + var args = new AzureOpenAiPromptExeTranslatorCommandLineArgs + { + DeploymentId = azureOpenAiDeploymentName, + EndpointId = azureOpenAiEndpoint, + SystemPrompt = AiSystemInstructions, + Credentials = azureOpenAiKey, + ExamplesInputString = ExamplesInputString, + ExamplesOutputString = ExamplesOutputString, + }; + + // The system prompt can't have double quotes in it, bkz those are used for separating the 4 command line parameters, + // So convert them to single quotes, which should also work + // return $"\"{projectId}\" \"{locationId}\" \"{publisher}\" \"{modelId}\" \"{VertexAiSystemPrompt.Replace("\"", "'")}\" \"{GoogleCloudVertexAiSubscriptionKey}\""; + var tempFilespec = args.SaveToTempFile(); + var arguments = $"\"{tempFilespec}\""; + return arguments; } } @@ -238,7 +248,7 @@ protected override EncodingForm DefaultUnicodeEncForm(bool bForward, bool bLHS) #endregion Misc helpers #region Abstract Base Class Overrides - protected override string GetConfigTypeName + protected override string GetConfigTypeName { get { return typeof(AzureOpenAiEncConverterConfig).AssemblyQualifiedName; } } diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config index db75f849..5eef4719 100644 --- a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/App.config @@ -1,4 +1,4 @@ - + @@ -19,7 +19,7 @@ - + @@ -27,11 +27,11 @@ - + - + @@ -39,7 +39,15 @@ - + + + + + + + + + diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj index af2704cb..28ee7c08 100644 --- a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/AzureOpenAiExe.csproj @@ -1,4 +1,4 @@ - + @@ -56,29 +56,34 @@ - ..\..\..\..\packages\Azure.AI.OpenAI.1.0.0-beta.8\lib\netstandard2.0\Azure.AI.OpenAI.dll + ..\..\..\..\packages\Azure.AI.OpenAI.1.0.0-beta.13\lib\netstandard2.0\Azure.AI.OpenAI.dll - - ..\..\..\..\packages\Azure.Core.1.35.0\lib\net472\Azure.Core.dll + + ..\..\..\..\packages\Azure.Core.1.37.0\lib\net472\Azure.Core.dll - - ..\..\..\..\packages\Microsoft.Bcl.AsyncInterfaces.7.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll - True + + ..\..\..\..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + ..\..\..\..\packages\System.ClientModel.1.0.0\lib\netstandard2.0\System.ClientModel.dll + - - ..\..\..\..\packages\System.Diagnostics.DiagnosticSource.7.0.2\lib\net462\System.Diagnostics.DiagnosticSource.dll + + ..\..\..\..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll ..\..\..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll True - - ..\..\..\..\packages\System.Memory.Data.7.0.0\lib\net462\System.Memory.Data.dll + + ..\..\..\..\packages\System.Memory.Data.8.0.0\lib\net462\System.Memory.Data.dll @@ -87,13 +92,11 @@ ..\..\..\..\packages\System.Runtime.CompilerServices.Unsafe.7.0.0-preview.2.22152.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll - - ..\..\..\..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll - True + + ..\..\..\..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll - - ..\..\..\..\packages\System.Text.Json.7.0.3\lib\net462\System.Text.Json.dll - True + + ..\..\..\..\packages\System.Text.Json.8.0.1\lib\net462\System.Text.Json.dll ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll @@ -109,6 +112,15 @@ + + PromptExeTranslatorCommandLineArgs.cs + + + RsaEncryptionClass.cs + + + AzureOpenAiPromptExeTranslatorCommandLineArgs.cs + diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs index dcc8bbef..d20ac166 100644 --- a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/Program.cs @@ -10,10 +10,15 @@ using System.Text; using System.Threading.Tasks; using System.IO; +using Newtonsoft.Json; +using SilEncConverters40.EcTranslators.VertexAi; +using System.Security.Policy; namespace SilEncConverters40.EcTranslators.AzureOpenAI.AzureOpenAiExe { - internal class Program + // for debugging: command line parameters are: + // gpt-translator-encconverter https://azure-openai-encconverter.openai.azure.com/ 5bc... "Translate from Hindi into English." + internal class Program { #if LogResults private const string LogFilePath = @"C:\btmp\AzureOpenAiLog.txt"; @@ -31,12 +36,23 @@ static async Task Main(string[] args) Console.InputEncoding = Encoding.Unicode; Console.OutputEncoding = Encoding.Unicode; - if (!IsValidParameters(args, out string deploymentName, out string endpoint, out string key, out string systemPrompt)) + string pathToEncryptedCommandLineParameterFile = null; + if ((args.Length == 0) || !File.Exists((pathToEncryptedCommandLineParameterFile = args[0]))) + { + Console.WriteLine(String.Format("Usage:{0}{0}{1} \"\"", Environment.NewLine, typeof(Program).Namespace)); + return; + } + + var contents = File.ReadAllText(pathToEncryptedCommandLineParameterFile); + var json = EncryptionClass.Decrypt(contents); + var arguments = JsonConvert.DeserializeObject(json); + + if (!IsValidParameters(arguments, out string deploymentName, out string endpoint, out string key, out string systemPrompt)) return; try { - await ProcessRequest(deploymentName, endpoint, key, systemPrompt); + await ProcessRequest(arguments, deploymentName, endpoint, key, systemPrompt); } catch (Exception ex) { @@ -44,17 +60,28 @@ static async Task Main(string[] args) } } - private static async Task ProcessRequest(string deploymentName, string endpoint, string key, string systemPrompt) + private static async Task ProcessRequest(AzureOpenAiPromptExeTranslatorCommandLineArgs arguments, string deploymentName, string endpoint, + string key, string systemPrompt) { // Pass the deployment name you chose when you created/deployed the model in Azure OpenAI Studio. var client = new OpenAIClient(new Uri(endpoint), new AzureKeyCredential(key)); // create the ChatMessages w/ the given systemPrompt - var chatMessages = new List + var chatMessages = new List { - new ChatMessage(ChatRole.System, systemPrompt) + new ChatRequestSystemMessage(systemPrompt) }; - var chatCompletionOptions = new ChatCompletionsOptions(chatMessages); + + // microsoft just does examples like they are previous communication w/ the model + var numberOfExamples = arguments.ExamplesInputString.Count; + for (int i = 0; i < numberOfExamples; i++) + { + chatMessages.Add(new ChatRequestUserMessage(arguments.ExamplesInputString[i])); + chatMessages.Add(new ChatRequestAssistantMessage(arguments.ExamplesOutputString[i])); + } + + var prefixMessages = chatMessages.Count; + var chatCompletionOptions = new ChatCompletionsOptions(deploymentName, chatMessages); // in case there are multiple lines (e.g. what Paratext will do if the verse has multiple paragraphs), // process in a while loop @@ -69,23 +96,29 @@ private static async Task ProcessRequest(string deploymentName, string endpoint, continue; // add the string to be translated to as the 'user' message - chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.User, strInput)); + + chatCompletionOptions.Messages.Add(new ChatRequestUserMessage(strInput)); + +#if LogResults + var json = JsonConvert.SerializeObject(chatCompletionOptions, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore }); + File.AppendAllText(LogFilePath, json + Environment.NewLine); +#endif // call the service to process the user msg based on the given system prompt - var chatCompletions = await client.GetChatCompletionsAsync(deploymentName, chatCompletionOptions); + var chatCompletions = await client.GetChatCompletionsAsync(chatCompletionOptions); // clean up and return the "assistent's response" var strOutput = HarvestResult(strInput, chatCompletions.Value.Choices[0]); // put that back in the chat, in case we are processing multiple lines // (this'll make them 'related' for better translation) - chatCompletionOptions.Messages.Add(new ChatMessage(ChatRole.Assistant, strOutput)); + chatCompletionOptions.Messages.Add(new ChatRequestAssistantMessage(strOutput)); } - for (var i = 1; i < chatCompletionOptions.Messages.Count;) + for (var i = prefixMessages; i < chatCompletionOptions.Messages.Count;) { - var strInput = chatCompletionOptions.Messages[i++].Content; - var strOutput = chatCompletionOptions.Messages[i++].Content; + var strInput = ((ChatRequestUserMessage)chatCompletionOptions.Messages[i++]).Content; + var strOutput = ((ChatRequestAssistantMessage)chatCompletionOptions.Messages[i++]).Content; #if LogResults File.AppendAllText(LogFilePath, string.Format("{1}=>{2}:{3}=>{4}{0}", Environment.NewLine, systemPrompt, i / 2, strInput, strOutput)); @@ -95,19 +128,19 @@ private static async Task ProcessRequest(string deploymentName, string endpoint, } } - private static bool IsValidParameters(string[] args, out string deploymentName, out string endpoint, out string key, out string systemPrompt) + private static bool IsValidParameters(AzureOpenAiPromptExeTranslatorCommandLineArgs arguments, out string deploymentName, out string endpoint, out string key, out string systemPrompt) { - if (args.Length != 4) - { - Console.WriteLine(String.Format("Usage:{0}{0}{1} \"\" \"\" \"\" \"\"", Environment.NewLine, typeof(Program).Namespace)); - deploymentName = endpoint = key = systemPrompt = null; - return false; - } + if (arguments == null) + { + Console.WriteLine(String.Format("Usage:{0}{0}{1} \"", Environment.NewLine, typeof(Program).Namespace)); + deploymentName = endpoint = systemPrompt = key = null; + return false; + } - deploymentName = args[0]; - endpoint = args[1]; - key = args[2]; - systemPrompt = args[3]; + deploymentName = arguments.DeploymentId; + endpoint = arguments.EndpointId; + key = arguments.Credentials; + systemPrompt = arguments.SystemPrompt; if (!IsValidParameter(EnvVarNameDeploymentName, ref deploymentName)) { @@ -133,7 +166,7 @@ private static bool IsValidParameters(string[] args, out string deploymentName, return false; } - return true; + return true; } private static bool IsValidParameter(string envVarName, ref string parameter) diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config index 41e54c84..2e2107b9 100644 --- a/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiExe/packages.config @@ -1,16 +1,18 @@  - - - + + + + - + + - + - - + + \ No newline at end of file diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiPromptExeTranslatorCommandLineArgs.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiPromptExeTranslatorCommandLineArgs.cs new file mode 100644 index 00000000..605a563a --- /dev/null +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiPromptExeTranslatorCommandLineArgs.cs @@ -0,0 +1,21 @@ +// #define encryptingNewCredentials + +namespace SilEncConverters40.EcTranslators.AzureOpenAI +{ + public class AzureOpenAiPromptExeTranslatorCommandLineArgs : PromptExeTranslatorCommandLineArgs + { + public string DeploymentId { get; set; } + public string EndpointId { get; set; } + + /// + /// What sampling temperature to use, between 0 and 2. Higher values means the model will take more risks. Try 0.9 for more creative applications, and 0 (argmax sampling) for ones with a well-defined answer. We generally recommend altering this or top_p but not both. + /// + public double? Temperature { get; set; } = 1; // (from 0-2) the default per https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#chat-completions + + /// + /// An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We generally recommend altering this or temperature but not both. + /// + public double? TopP { get; set; } = 1; // default + } +} + diff --git a/src/EcTranslators/EcTranslators.csproj b/src/EcTranslators/EcTranslators.csproj index f5be9094..ec4b7c85 100644 --- a/src/EcTranslators/EcTranslators.csproj +++ b/src/EcTranslators/EcTranslators.csproj @@ -90,6 +90,7 @@ QueryForAzureKeyDeploymentNameAndEndpoint.cs + Form @@ -168,6 +169,8 @@ QueryForEndpointAndApiKey.cs + + True @@ -181,6 +184,21 @@ + + Form + + + QueryForGoogleCredentials.cs + + + Form + + + VertexAiAutoConfigDialog.cs + + + + @@ -226,6 +244,12 @@ Resources.Designer.cs Designer + + QueryForGoogleCredentials.cs + + + VertexAiAutoConfigDialog.cs + @@ -260,28 +284,28 @@ 4.4.0 - 1.62.1 + 1.66.0 - 1.62.1 + 1.66.0 - 1.62.1 + 1.66.0 - 1.62.0.875 + 1.66.0.875 3.2.0 - 7.0.0 + 8.0.0 - 7.0.4 + 8.0.1 - 7.0.13 + 8.0.1 13.0.3 @@ -290,19 +314,19 @@ 6.0.0-preview.4.21253.7 - 7.0.2 + 8.0.0 4.5.5 - 7.0.0 + 8.0.0 7.0.0-preview.2.22152.2 - 7.0.3 + 8.0.1 diff --git a/src/EcTranslators/PromptExeTranslatorCommandLineArgs.cs b/src/EcTranslators/PromptExeTranslatorCommandLineArgs.cs new file mode 100644 index 00000000..77ce6017 --- /dev/null +++ b/src/EcTranslators/PromptExeTranslatorCommandLineArgs.cs @@ -0,0 +1,43 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace SilEncConverters40.EcTranslators +{ + public class PromptExeTranslatorCommandLineArgs + { + public List ExamplesInputString { get; set; } + public List ExamplesOutputString { get; set; } + public string SystemPrompt { get; set; } + public string Credentials { get; set; } + + public override string ToString() + { + var json = JsonConvert.SerializeObject(this); + var base64 = StringToBase64(json); + return base64; + /* e.g for VertexAi + H=>E: eyJQcm9qZWN0SWQiOiJicmlnaHQtY295b3RlLTM4MTgxMiIsIkxvY2F0aW9uSWQiOiJ1cy1jZW50cmFsMSIsIlB1Ymxpc2hlciI6Imdvb2dsZSIsIk1vZGVsSWQiOiJjaGF0LWJpc29uLTMyayIsIkV4YW1wbGVJbnB1dFN0cmluZyI6IuCkuOClg+Ckt+CljeCkn+CkvyDgpJXgpYcg4KSG4KSw4KSC4KStIOCkuOClhyDgpLLgpYfgpJXgpLAg4KSq4KSw4KSu4KWH4KS24KWN4KS14KSwIOCksuCli+Ckl+Cli+CkgiDgpKrgpLAg4KSF4KSq4KSo4KWAIOCkh+CkmuCljeKAjeCkm+CkvuCkj+CkgSwg4KSs4KS54KWB4KSkIOCkrOCkvuCksCDgpK3gpL/gpKjgpY3igI3gpKgt4KSt4KS/4KSo4KWN4oCN4KSoIOCkquCljeCksOCkleCkvuCksCDgpLjgpYcg4KSq4KWN4KSw4KSV4KSfIOCkleCksOCkpOCkviDgpIbgpK/gpL4g4KS54KWI4KWkIOCkueCkruCkvuCksOClhyDgpKrgpYLgpLDgpY3gpLXgpJzgpYvgpIIg4KSV4KWHIOCkr+ClgeCklyDgpK7gpYfgpIIg4KSt4KWAIOCkquCksOCkruClh+CktuCljeCkteCksCDgpLjgpILgpKQt4KSu4KS54KS+4KSk4KWN4oCN4KSu4KS+4KST4KSCIOCkleClhyDgpKbgpY3gpLXgpL7gpLDgpL4g4KSF4KSq4KSo4KS+IOCkuOCkguCkpuClh+CktiDgpK3gpYfgpJzgpKTgpL4g4KSl4KS+4KWkIiwiRXhhbXBsZU91dHB1dFN0cmluZyI6IlNpbmNlIHRoZSBiZWdpbm5pbmcgb2YgY3JlYXRpb24sIEdvZCBoYXMgcmV2ZWFsZWQgSGlzIHdpbGwgdG8gbWFua2luZCBtYW55IHRpbWVzIGluIGRpZmZlcmVudCB3YXlzLiBFdmVuIGluIHRoZSBlcmEgb2Ygb3VyIGFuY2VzdG9ycywgR29kIHVzZWQgdG8gc2VuZCBIaXMgbWVzc2FnZSB0aHJvdWdoIHNhaW50cyBhbmQgcHJvcGhldHMuIiwiU3lzdGVtUHJvbXB0IjoiWW91IHdpbGwgYmUgZ2l2ZW4gMSBvciBtb3JlIGxpbmVzIG9mIHRleHQgaW4gSGluZGkgd2hpY2ggeW91IGFyZSB0byB0cmFuc2xhdGUgaW50byBFbmdsaXNoIFRyYW5zbGF0ZSBmcm9tIEhpbmRpIGludG8gRW5nbGlzaC4gYW5kIHJldHVybiBvbmx5IHRoZSB0cmFuc2xhdGVkIGxpbmVzLiIsIkNyZWRlbnRpYWxzIjoieyAgJ3R5cGUnOiAnc2VydmljZV9hY2NvdW50JywgICdwcm9qZWN0X2lkJzogJ2JyaWdodC1jb3lvdGUtMzgxODEyJywgICdwcml2YXRlX2tleV9pZCc6ICdiYzU4NGNlYzAwN2ZhOTcxMTcyMzE5ZDk0MWIwMzVhOWJlNjUzM2RlJywgICdwcml2YXRlX2tleSc6ICctLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cbk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRGNrUFdBaUEzaVRiQURcbm4wSmQxK29vbGZtNHVNSW5JZ2VVVE5tVHJFeEhET05xZTJZamI3VWVkUjdPMGlGaVJkOW1NaEk2RVpFWStoaWhcbmhFcndEOEVSZjdLRkxrdmRyTjgyOUIvejU5bFFLYWZiTjlHUGNmdUpDTGdheGVqUXAwL3dMMFBkcFF6ZmZMQ3hcbk9pdjlKZGwyOWk0S053N2IvaE05Tys3OWluclRKLzRzRnJtZXpoMjBHY205NVNFNWo4MTkyakRmUWdTV05KV3VcbjZVb1ZyTlJPWVIxV1o3cUp0OTVsQ1lScitydTJBVGxPaTJvbTFldEVwUE1Wd0hTeHZIcElYYVFKdisxaHdDYldcbmZuYjE2bTNWR2t3bnk3YXBnNGtIWEZxSnpqeGJqVm9pYTE4OCtON2FOekQyTEdMMW1nR2l3dUxzSzNHNnVLZnlcblkyeXRKUWpoQWdNQkFBRUNnZ0VBQlVNWTlORTJJOVhzdFA3cVIrUHZPV3IzMEYrcHkrSkZyQlRMNkhCSytQTllcbmUvdHovclNmSllvSHQwbGppQkUwdnQ3aklQOFhHeUY1RjhZZ3ZhN0NDV0pla0d0bi9tSzkxKzFCdzRWZW1abEhcblVMRkprTlNRU3JyK1RhNzIzcDY5dnpRbytFMVVKL010RWRyYWRwOTk4MWJrNXZ2c21ReDBFZjBEZHZsOE0vdzJcbkJydC94MjN3YUt1WS90NE1TYUdTbklad281Wm94YTJxN2dvMFYvWk4zMC9LaGlLQVhLS1ZPRkJkZUVkQ0VneDhcbktPZThhOEI2VjZBcG13UFVoTWwvdnlFNWlxY00vVXhtN1FEbFdidUxoS3o3ZFVEaFIwOXUzbTlQc1Q0bXBIMFBcbnd5NWM3bVA4TkwrT1drQ1ZkYmNXOUZPL2E2dzZKclBreHVQNVZrNk5RUUtCZ1FEeVRBNkRmZUFNVEF1RUllVUJcbmJ6OUZ5T0xxK0poVEkwTFZwUFBXaDkyZmtjUXJ5ZFFpTmZ4REJPYXAyUXN1RWo4bWc2dnFCUHpSamV0UmM1UjRcblM0TWJDOGZab3hEeEtZY0tSOUo2dTgzSXFpOHh2amFHcjlNekIzRnF0WkVsUHFKdFFhTC9yRWJvamFhS1J0WEdcbnBVSE9TMGxuc3pKRGJBMldOSXoyT0lCZ29RS0JnUURwQ2trOTZaZ0IzVjVkcndiMXowenh6MFJsQlZ3Y3dDM3JcblZSMkhUQnUweHRIT0FYOVpYc25tb3pJdXk3RmxUUmdJeXNjTkVsTlBtR2M1NC9Zdkt1OVZobElDSEVzT0I1b3NcblNUSmh4VnVBdE01Z2hJTXlmZ1Z0UHVPaWt4Vm93RjJRSnBRWC9rbFU4YWZ3MmQ0dE5yVVBXWUl3c1FWZDUwT2hcblB6dGNicnlBUVFLQmdCZjhuNU0wNnZGTXRmY213OTBZZmxNU1NDU3E1Nm1UWEJKNmVnbEsrZzNLQ0htdFNXcjVcbm5UZWxUSkNVQkI5VGZ4ejQvQlAyMm5DRWREOWtDZGErNHdQU2JyNkUvakJoeEJTb2Q1WGU4Y2hqMExoRDlISHhcbkJoK1BKUk5EVmxNeG1ETG94Skk3SStueDNBTGtjRlZ5RnNtdGVsN2h4cUFXR21JOFlaZ2VqOWNCQW9HQkFOR2FcbmdOb0Erc25pay9mcmIzVTBLVjd0TC9VMDV1NnRKQ0FoQkZnbTZseWszeHhOV0gvSHRBMlFCNWp6ZVBGR2NER29cblFYVE9ZTVNjcld2eVVBR0l1by9RS243ZmQ5cDhsL3p4TVRHalUzUG1MQ0cvemtsaDgvdVlyeUlRN1JhMHZ2TGlcbjRCemNpSlN3Ym45QlZvYVFTRFl3S2RzbHZWQUNyRitpQWdCWFVaQ0JBb0dBS2xXU1Z4aUFjUXZsZVdHT1hHWTZcbjdUVWdoOXAwdmx1Y2gwWXVFV1A3MEJRVDdmYjIzeUdUMWU0aWtLbWtueUhHQWtEZlZ1bzE2WCs3S0c3cnVpNWFcbldwRWdVc3FKcWlVcC9RVVlmcDZlVWhJMzdGQlVyeEg0eXFNeXZvY3BuUUhSQ2Z6NFBnaXJzSmdOdmJYa25aVE1cbk9HZjRqdGovWk1OV3gwd3c4RE5nTzNRPVxuLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLVxuJywgICdjbGllbnRfZW1haWwnOiAndmVydGV4YWllbmNjb252ZXJ0ZXJAYnJpZ2h0LWNveW90ZS0zODE4MTIuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20nLCAgJ2NsaWVudF9pZCc6ICcxMTYxMTM1NDE1NjY4OTI5MjM2OTInLCAgJ2F1dGhfdXJpJzogJ2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi9hdXRoJywgICd0b2tlbl91cmknOiAnaHR0cHM6Ly9vYXV0aDIuZ29vZ2xlYXBpcy5jb20vdG9rZW4nLCAgJ2F1dGhfcHJvdmlkZXJfeDUwOV9jZXJ0X3VybCc6ICdodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9vYXV0aDIvdjEvY2VydHMnLCAgJ2NsaWVudF94NTA5X2NlcnRfdXJsJzogJ2h0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3JvYm90L3YxL21ldGFkYXRhL3g1MDkvdmVydGV4YWllbmNjb252ZXJ0ZXIlNDBicmlnaHQtY295b3RlLTM4MTgxMi5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbScsICAndW5pdmVyc2VfZG9tYWluJzogJ2dvb2dsZWFwaXMuY29tJ30ifQ== + E=>H: eyJQcm9qZWN0SWQiOiJicmlnaHQtY295b3RlLTM4MTgxMiIsIkxvY2F0aW9uSWQiOiJ1cy1jZW50cmFsMSIsIlB1Ymxpc2hlciI6Imdvb2dsZSIsIk1vZGVsSWQiOiJjaGF0LWJpc29uLTMyayIsIlRlbXBlcmF0dXJlIjowLjMsIk1heERlY29kZVN0ZXBzIjoyMDAsIlRvcFAiOjAuOCwiVG9wSyI6NDAsIkV4YW1wbGVJbnB1dFN0cmluZyI6bnVsbCwiRXhhbXBsZU91dHB1dFN0cmluZyI6bnVsbCwiU3lzdGVtUHJvbXB0IjoiWW91IHdpbGwgYmUgZ2l2ZW4gMSBvciBtb3JlIGxpbmVzIG9mIHRleHQgaW4gRW5nbGlzaCB3aGljaCB5b3UgYXJlIHRvIHRyYW5zbGF0ZSBpbnRvIEhpbmRpIHdpdGggYSBcImZyZWUgdHJhbnNsYXRpb25cIiBzdHlsZSBhaW1lZCBhdCBoaWdoIHNjaG9vbCBzdHVkZW50cyBhbmQgcmV0dXJuIG9ubHkgdGhlIHRyYW5zbGF0ZWQgbGluZXMuIiwiQ3JlZGVudGlhbHMiOiJ7ICAndHlwZSc6ICdzZXJ2aWNlX2FjY291bnQnLCAgJ3Byb2plY3RfaWQnOiAnYnJpZ2h0LWNveW90ZS0zODE4MTInLCAgJ3ByaXZhdGVfa2V5X2lkJzogJ2JjNTg0Y2VjMDA3ZmE5NzExNzIzMTlkOTQxYjAzNWE5YmU2NTMzZGUnLCAgJ3ByaXZhdGVfa2V5JzogJy0tLS0tQkVHSU4gUFJJVkFURSBLRVktLS0tLVxuTUlJRXZRSUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NCS2N3Z2dTakFnRUFBb0lCQVFEY2tQV0FpQTNpVGJBRFxubjBKZDErb29sZm00dU1JbklnZVVUTm1UckV4SERPTnFlMllqYjdVZWRSN08waUZpUmQ5bU1oSTZFWkVZK2hpaFxuaEVyd0Q4RVJmN0tGTGt2ZHJOODI5Qi96NTlsUUthZmJOOUdQY2Z1SkNMZ2F4ZWpRcDAvd0wwUGRwUXpmZkxDeFxuT2l2OUpkbDI5aTRLTnc3Yi9oTTlPKzc5aW5yVEovNHNGcm1lemgyMEdjbTk1U0U1ajgxOTJqRGZRZ1NXTkpXdVxuNlVvVnJOUk9ZUjFXWjdxSnQ5NWxDWVJyK3J1MkFUbE9pMm9tMWV0RXBQTVZ3SFN4dkhwSVhhUUp2KzFod0NiV1xuZm5iMTZtM1ZHa3dueTdhcGc0a0hYRnFKemp4YmpWb2lhMTg4K043YU56RDJMR0wxbWdHaXd1THNLM0c2dUtmeVxuWTJ5dEpRamhBZ01CQUFFQ2dnRUFCVU1ZOU5FMkk5WHN0UDdxUitQdk9XcjMwRitweStKRnJCVEw2SEJLK1BOWVxuZS90ei9yU2ZKWW9IdDBsamlCRTB2dDdqSVA4WEd5RjVGOFlndmE3Q0NXSmVrR3RuL21LOTErMUJ3NFZlbVpsSFxuVUxGSmtOU1FTcnIrVGE3MjNwNjl2elFvK0UxVUovTXRFZHJhZHA5OTgxYms1dnZzbVF4MEVmMERkdmw4TS93MlxuQnJ0L3gyM3dhS3VZL3Q0TVNhR1NuSVp3bzVab3hhMnE3Z28wVi9aTjMwL0toaUtBWEtLVk9GQmRlRWRDRWd4OFxuS09lOGE4QjZWNkFwbXdQVWhNbC92eUU1aXFjTS9VeG03UURsV2J1TGhLejdkVURoUjA5dTNtOVBzVDRtcEgwUFxud3k1YzdtUDhOTCtPV2tDVmRiY1c5Rk8vYTZ3NkpyUGt4dVA1Vms2TlFRS0JnUUR5VEE2RGZlQU1UQXVFSWVVQlxuYno5RnlPTHErSmhUSTBMVnBQUFdoOTJma2NRcnlkUWlOZnhEQk9hcDJRc3VFajhtZzZ2cUJQelJqZXRSYzVSNFxuUzRNYkM4ZlpveER4S1ljS1I5SjZ1ODNJcWk4eHZqYUdyOU16QjNGcXRaRWxQcUp0UWFML3JFYm9qYWFLUnRYR1xucFVIT1MwbG5zekpEYkEyV05JejJPSUJnb1FLQmdRRHBDa2s5NlpnQjNWNWRyd2IxejB6eHowUmxCVndjd0MzclxuVlIySFRCdTB4dEhPQVg5Wlhzbm1vekl1eTdGbFRSZ0l5c2NORWxOUG1HYzU0L1l2S3U5VmhsSUNIRXNPQjVvc1xuU1RKaHhWdUF0TTVnaElNeWZnVnRQdU9pa3hWb3dGMlFKcFFYL2tsVThhZncyZDR0TnJVUFdZSXdzUVZkNTBPaFxuUHp0Y2JyeUFRUUtCZ0JmOG41TTA2dkZNdGZjbXc5MFlmbE1TU0NTcTU2bVRYQko2ZWdsSytnM0tDSG10U1dyNVxublRlbFRKQ1VCQjlUZnh6NC9CUDIybkNFZEQ5a0NkYSs0d1BTYnI2RS9qQmh4QlNvZDVYZThjaGowTGhEOUhIeFxuQmgrUEpSTkRWbE14bURMb3hKSTdJK254M0FMa2NGVnlGc210ZWw3aHhxQVdHbUk4WVpnZWo5Y0JBb0dCQU5HYVxuZ05vQStzbmlrL2ZyYjNVMEtWN3RML1UwNXU2dEpDQWhCRmdtNmx5azN4eE5XSC9IdEEyUUI1anplUEZHY0RHb1xuUVhUT1lNU2NyV3Z5VUFHSXVvL1FLbjdmZDlwOGwvenhNVEdqVTNQbUxDRy96a2xoOC91WXJ5SVE3UmEwdnZMaVxuNEJ6Y2lKU3dibjlCVm9hUVNEWXdLZHNsdlZBQ3JGK2lBZ0JYVVpDQkFvR0FLbFdTVnhpQWNRdmxlV0dPWEdZNlxuN1RVZ2g5cDB2bHVjaDBZdUVXUDcwQlFUN2ZiMjN5R1QxZTRpa0tta255SEdBa0RmVnVvMTZYKzdLRzdydWk1YVxuV3BFZ1VzcUpxaVVwL1FVWWZwNmVVaEkzN0ZCVXJ4SDR5cU15dm9jcG5RSFJDZno0UGdpcnNKZ052YlhrblpUTVxuT0dmNGp0ai9aTU5XeDB3dzhETmdPM1E9XG4tLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tXG4nLCAgJ2NsaWVudF9lbWFpbCc6ICd2ZXJ0ZXhhaWVuY2NvbnZlcnRlckBicmlnaHQtY295b3RlLTM4MTgxMi5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbScsICAnY2xpZW50X2lkJzogJzExNjExMzU0MTU2Njg5MjkyMzY5MicsICAnYXV0aF91cmknOiAnaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL2F1dGgnLCAgJ3Rva2VuX3VyaSc6ICdodHRwczovL29hdXRoMi5nb29nbGVhcGlzLmNvbS90b2tlbicsICAnYXV0aF9wcm92aWRlcl94NTA5X2NlcnRfdXJsJzogJ2h0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92MS9jZXJ0cycsICAnY2xpZW50X3g1MDlfY2VydF91cmwnOiAnaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vcm9ib3QvdjEvbWV0YWRhdGEveDUwOS92ZXJ0ZXhhaWVuY2NvbnZlcnRlciU0MGJyaWdodC1jb3lvdGUtMzgxODEyLmlhbS5nc2VydmljZWFjY291bnQuY29tJywgICd1bml2ZXJzZV9kb21haW4nOiAnZ29vZ2xlYXBpcy5jb20nfSJ9 + */ + + static string StringToBase64(string plainText) + { + byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); + return Convert.ToBase64String(plainTextBytes); + } + } + + public string SaveToTempFile() + { + var tempFilespec = Path.GetTempFileName(); + var json = JsonConvert.SerializeObject(this); + var encrypted = EncryptionClass.Encrypt(json); + File.WriteAllText(tempFilespec, encrypted); + System.Diagnostics.Debug.WriteLine($"file: {tempFilespec} contains: {json}"); + return tempFilespec; + } + } +} diff --git a/src/EcTranslators/PromptTranslator.cs b/src/EcTranslators/PromptTranslator.cs new file mode 100644 index 00000000..21c1884c --- /dev/null +++ b/src/EcTranslators/PromptTranslator.cs @@ -0,0 +1,41 @@ +using ECInterfaces; +using SilEncConverters40.EcTranslators.AzureOpenAI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace SilEncConverters40.EcTranslators +{ + public abstract class PromptExeTranslator : ExeEncConverter + { + public List ExamplesInputString { get; set; } = new List(); + public List ExamplesOutputString { get; set; } = new List(); + + + public PromptExeTranslator + ( + string strProgramID, // usually "typeof().FullName", e.g. typeof(AzureOpenAiEncConverter).FullName + string strImplType, // e.g. (cf. SIL.AzureOpenAi) + Int32 lProcessType = (int)ProcessTypeFlags.Translation, // e.g. ProcessTypeFlags.Translation + string strWorkingDirSuffix = "" // e.g. @"\SIL\Indic\ITrans" (if installed there) + ) + : base(strProgramID, strImplType, ConvType.Unicode_to_Unicode, "UNICODE", "UNICODE", lProcessType, strWorkingDirSuffix) + { + } + + public virtual void AddExample(string inputString, string outputString) + { + ExamplesInputString.Add(inputString); + ExamplesOutputString.Add(outputString); + m_psi = null; // to force it to re-pull the Arguments, including these examples + } + + public virtual void PurgeExamples() + { + ExamplesInputString.Clear(); + ExamplesOutputString.Clear(); + m_psi = null; // to force it to re-pull the Arguments, including these examples + } + } +} diff --git a/src/EcTranslators/Properties/Resources.Designer.cs b/src/EcTranslators/Properties/Resources.Designer.cs index 095be2f3..c4517ec2 100644 --- a/src/EcTranslators/Properties/Resources.Designer.cs +++ b/src/EcTranslators/Properties/Resources.Designer.cs @@ -63,10 +63,7 @@ internal Resources() { /// /// Looks up a localized string similar to docker build -t nllb{0} . ///docker run -p {1}:{1} nllb{0} - ///Start-Process http://localhost:{1}/ - /// - ///Write-output "Make sure there are no errors and that the page at 'http://localhost:{1}' is able to translate before using in SILConverters" - ///pause . + ///# Start-Process http://localhost:{1}/. /// internal static string buildDocker { get { @@ -99,6 +96,15 @@ internal static string Dockerfile { } } + /// + /// Looks up a localized string similar to https://cloud.google.com/vertex-ai/docs/start/cloud-environment. + /// + internal static string GoogleCloudVertexCredentialsDialogInstructionUrl { + get { + return ResourceManager.GetString("GoogleCloudVertexCredentialsDialogInstructionUrl", resourceCulture); + } + } + /// /// Looks up a localized string similar to https://cloud.google.com/translate/docs/setup#creating_service_accounts_and_keys. /// @@ -328,6 +334,87 @@ internal static string HelpForNllbTranslatorTargetLanguagesComboBox { } } + /// + /// Looks up a localized string similar to Click this button to enter your own Google Cloud credential key. Follow the instructions on the page, https://cloud.google.com/vertex-ai/docs/start/cloud-environment, to get create your own Google Cloud Translate service and get your own credentials (e.g. if the default credentials have run out of translation support. + /// + internal static string HelpForVertexAiAddYourOwnApiKey { + get { + return ResourceManager.GetString("HelpForVertexAiAddYourOwnApiKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the location id of the Google Cloud Vertex AI resource (e.g. us-central1). + /// + internal static string HelpForVertexAiLocationIdTextBox { + get { + return ResourceManager.GetString("HelpForVertexAiLocationIdTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the model id of the Google Cloud Vertex AI resource (e.g. chat-bison, chat-bison-32k, or gemini-pro). + /// + internal static string HelpForVertexAiModelIdTextBox { + get { + return ResourceManager.GetString("HelpForVertexAiModelIdTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the id of the Google Cloud Project that contains the Vertex AI resource. + /// + internal static string HelpForVertexAiProjectIdTextBox { + get { + return ResourceManager.GetString("HelpForVertexAiProjectIdTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the publisher of the Google Cloud Vertex AI resource (e.g. google). + /// + internal static string HelpForVertexAiPublisherTextBox { + get { + return ResourceManager.GetString("HelpForVertexAiPublisherTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the name of the language you want the Vertex AI Model to tranlate from (e.g. Hindi). + /// + internal static string HelpForVertexAiSourceLanguageTextBox { + get { + return ResourceManager.GetString("HelpForVertexAiSourceLanguageTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can add one of the existing additions to the base system prompt using the values in this drop down box (or type in your own). + /// + internal static string HelpForVertexAiSystemPromptAdditionsComboBox { + get { + return ResourceManager.GetString("HelpForVertexAiSystemPromptAdditionsComboBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This box shows the System Prompt that will be sent to the Vertext AI Model. + /// + internal static string HelpForVertexAiSystemPromptTextBox { + get { + return ResourceManager.GetString("HelpForVertexAiSystemPromptTextBox", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Enter the name of the language you want the Vertex AI Model to tranlate into (e.g. English). + /// + internal static string HelpForVertexAiTargetLanguageTextBox { + get { + return ResourceManager.GetString("HelpForVertexAiTargetLanguageTextBox", resourceCulture); + } + } + /// /// Looks up a localized string similar to # This file exists because: ///# 1. Documentation for using transformers often shows how to download them in Python @@ -399,6 +486,7 @@ internal static string README { /// /// Looks up a localized string similar to from flask import Flask, render_template, request, jsonify ///from settings import MODEL_NAME, PORT, API_KEY + ///from gevent.pywsgi import WSGIServer /// ///app = Flask(__name__) /// @@ -412,8 +500,7 @@ internal static string README { /// ///@app.route('/') ///def send_report(): - /// # Check if the API key is present in the request headers - /// if [rest of string was truncated]";. + /// # Check if the API key is [rest of string was truncated]";. /// internal static string server { get { diff --git a/src/EcTranslators/Properties/Resources.resx b/src/EcTranslators/Properties/Resources.resx index 4a4192cb..07490fd6 100644 --- a/src/EcTranslators/Properties/Resources.resx +++ b/src/EcTranslators/Properties/Resources.resx @@ -127,6 +127,9 @@ ..\nllbtranslator\docker\dockerfile;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + https://cloud.google.com/vertex-ai/docs/start/cloud-environment + https://cloud.google.com/translate/docs/setup#creating_service_accounts_and_keys @@ -206,6 +209,33 @@ See https://docs.microsoft.com/en-us/azure/cognitive-services/translator/languag Choose the language you want the input text to be translated into. + + Click this button to enter your own Google Cloud credential key. Follow the instructions on the page, https://cloud.google.com/vertex-ai/docs/start/cloud-environment, to get create your own Google Cloud Translate service and get your own credentials (e.g. if the default credentials have run out of translation support + + + Enter the location id of the Google Cloud Vertex AI resource (e.g. us-central1) + + + Enter the model id of the Google Cloud Vertex AI resource (e.g. chat-bison, chat-bison-32k, or gemini-pro) + + + Enter the id of the Google Cloud Project that contains the Vertex AI resource + + + Enter the publisher of the Google Cloud Vertex AI resource (e.g. google) + + + Enter the name of the language you want the Vertex AI Model to tranlate from (e.g. Hindi) + + + You can add one of the existing additions to the base system prompt using the values in this drop down box (or type in your own) + + + This box shows the System Prompt that will be sent to the Vertext AI Model + + + Enter the name of the language you want the Vertex AI Model to tranlate into (e.g. English) + ..\nllbtranslator\docker\import_model.py;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 diff --git a/src/EcTranslators/Properties/Settings.Designer.cs b/src/EcTranslators/Properties/Settings.Designer.cs index 320a682e..8b2b5067 100644 --- a/src/EcTranslators/Properties/Settings.Designer.cs +++ b/src/EcTranslators/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace SilEncConverters40.EcTranslators.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -313,5 +313,77 @@ public bool NllbProcessSentenceBySentence { return ((bool)(this["NllbProcessSentenceBySentence"])); } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string GoogleCloudVertexAiCredentials { + get { + return ((string)(this["GoogleCloudVertexAiCredentials"])); + } + set { + this["GoogleCloudVertexAiCredentials"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string GoogleCloudVertexAiCredentialsOverride { + get { + return ((string)(this["GoogleCloudVertexAiCredentialsOverride"])); + } + set { + this["GoogleCloudVertexAiCredentialsOverride"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string GoogleCloudVertexAiProjectId { + get { + return ((string)(this["GoogleCloudVertexAiProjectId"])); + } + set { + this["GoogleCloudVertexAiProjectId"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("us-central1")] + public string GoogleCloudVertexAiLocationId { + get { + return ((string)(this["GoogleCloudVertexAiLocationId"])); + } + set { + this["GoogleCloudVertexAiLocationId"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("google")] + public string GoogleCloudVertexAiPublisher { + get { + return ((string)(this["GoogleCloudVertexAiPublisher"])); + } + set { + this["GoogleCloudVertexAiPublisher"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("chat-bison")] + public string GoogleCloudVertexAiModelId { + get { + return ((string)(this["GoogleCloudVertexAiModelId"])); + } + set { + this["GoogleCloudVertexAiModelId"] = value; + } + } } } diff --git a/src/EcTranslators/Properties/Settings.settings b/src/EcTranslators/Properties/Settings.settings index 5371ca51..6bf0cf38 100644 --- a/src/EcTranslators/Properties/Settings.settings +++ b/src/EcTranslators/Properties/Settings.settings @@ -73,5 +73,23 @@ False + + + + + + + + + + + us-central1 + + + google + + + chat-bison + \ No newline at end of file diff --git a/src/EcTranslators/TranslatorConverter.cs b/src/EcTranslators/TranslatorConverter.cs index 83e8f254..6f349096 100644 --- a/src/EcTranslators/TranslatorConverter.cs +++ b/src/EcTranslators/TranslatorConverter.cs @@ -35,7 +35,7 @@ internal static unsafe void StringToProperByteStar(string strOutput, byte* lpOut ECNormalizeData.StringToByteStar(strOutput, lpOutBuffer, rnOutLen, false); } - internal static string LogExceptionMessage(string className, Exception ex) + public static string LogExceptionMessage(string className, Exception ex) { var message = ex.Message; var msg = "Error occurred: " + message; diff --git a/src/EcTranslators/VertexAi/QueryForGoogleCredentials.Designer.cs b/src/EcTranslators/VertexAi/QueryForGoogleCredentials.Designer.cs new file mode 100644 index 00000000..d0e612ce --- /dev/null +++ b/src/EcTranslators/VertexAi/QueryForGoogleCredentials.Designer.cs @@ -0,0 +1,148 @@ + +namespace SilEncConverters40.EcTranslators.VertexAi +{ + partial class QueryForGoogleCredentials + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.buttonOK = new System.Windows.Forms.Button(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.labelTranslatorKey = new System.Windows.Forms.Label(); + this.textBoxTranslatorKey = new System.Windows.Forms.TextBox(); + this.linkLabelInstructions = new System.Windows.Forms.LinkLabel(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel1.AutoSize = true; + this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 65F)); + this.tableLayoutPanel1.Controls.Add(this.buttonOK, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.buttonCancel, 2, 2); + this.tableLayoutPanel1.Controls.Add(this.labelTranslatorKey, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxTranslatorKey, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.linkLabelInstructions, 0, 1); + this.tableLayoutPanel1.Location = new System.Drawing.Point(12, 12); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 3; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(659, 368); + this.tableLayoutPanel1.TabIndex = 0; + // + // buttonOK + // + this.buttonOK.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.buttonOK.Location = new System.Drawing.Point(287, 342); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.Size = new System.Drawing.Size(75, 23); + this.buttonOK.TabIndex = 6; + this.buttonOK.Text = "&OK"; + this.buttonOK.UseVisualStyleBackColor = true; + this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + // + // buttonCancel + // + this.buttonCancel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(368, 342); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.TabIndex = 7; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = true; + // + // labelTranslatorKey + // + this.labelTranslatorKey.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelTranslatorKey.AutoSize = true; + this.labelTranslatorKey.Location = new System.Drawing.Point(3, 138); + this.labelTranslatorKey.Name = "labelTranslatorKey"; + this.labelTranslatorKey.Size = new System.Drawing.Size(202, 13); + this.labelTranslatorKey.TabIndex = 1; + this.labelTranslatorKey.Text = "Enter Google Cloud/Vertex Credentials (json):"; + // + // textBoxTranslatorKey + // + this.tableLayoutPanel1.SetColumnSpan(this.textBoxTranslatorKey, 2); + this.textBoxTranslatorKey.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxTranslatorKey.Location = new System.Drawing.Point(211, 3); + this.textBoxTranslatorKey.Multiline = true; + this.textBoxTranslatorKey.Name = "textBoxTranslatorKey"; + this.textBoxTranslatorKey.Size = new System.Drawing.Size(445, 283); + this.textBoxTranslatorKey.TabIndex = 2; + // + // linkLabelInstructions + // + this.linkLabelInstructions.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.linkLabelInstructions.AutoSize = true; + this.tableLayoutPanel1.SetColumnSpan(this.linkLabelInstructions, 3); + this.linkLabelInstructions.Location = new System.Drawing.Point(3, 307); + this.linkLabelInstructions.Name = "linkLabelInstructions"; + this.linkLabelInstructions.Size = new System.Drawing.Size(347, 13); + this.linkLabelInstructions.TabIndex = 5; + this.linkLabelInstructions.TabStop = true; + this.linkLabelInstructions.Text = "see {0} for instructions on creating your own Google Cloud/Vertex Resource"; + this.linkLabelInstructions.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelInstructions_LinkClicked); + // + // QueryForGoogleCredentials + // + this.AcceptButton = this.buttonOK; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(686, 392); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "QueryForGoogleCredentials"; + this.Text = "Enter Google Cloud/Vertex API Credentials"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Label labelTranslatorKey; + private System.Windows.Forms.TextBox textBoxTranslatorKey; + private System.Windows.Forms.LinkLabel linkLabelInstructions; + } +} \ No newline at end of file diff --git a/src/EcTranslators/VertexAi/QueryForGoogleCredentials.cs b/src/EcTranslators/VertexAi/QueryForGoogleCredentials.cs new file mode 100644 index 00000000..1ce31f96 --- /dev/null +++ b/src/EcTranslators/VertexAi/QueryForGoogleCredentials.cs @@ -0,0 +1,41 @@ +using System.Diagnostics; +using System.Windows.Forms; + +namespace SilEncConverters40.EcTranslators.VertexAi +{ + public partial class QueryForGoogleCredentials : Form + { + private const string InstructionsFormat = "see {0} for instructions on creating your own Google Cloud/Vertex Resource"; + + public QueryForGoogleCredentials(string googleTranslatorCredentials) + { + InitializeComponent(); + + textBoxTranslatorKey.Text = googleTranslatorCredentials; + var translatorKeyLocationDialogInstructionUrl = Properties.Resources.GoogleCloudVertexCredentialsDialogInstructionUrl; + var translatorKeyLocationDialogInstruction = string.Format(InstructionsFormat, translatorKeyLocationDialogInstructionUrl); + linkLabelInstructions.Text = translatorKeyLocationDialogInstruction; + linkLabelInstructions.Links.Add(4, translatorKeyLocationDialogInstructionUrl.Length, + translatorKeyLocationDialogInstructionUrl); + } + + public string TranslatorKey + { + get + { + return textBoxTranslatorKey.Text; + } + } + + private void linkLabelInstructions_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + Process.Start(Properties.Resources.GoogleCloudVertexCredentialsDialogInstructionUrl); + } + + private void buttonOK_Click(object sender, System.EventArgs e) + { + DialogResult = DialogResult.OK; + Close(); + } + } +} diff --git a/src/EcTranslators/VertexAi/QueryForGoogleCredentials.resx b/src/EcTranslators/VertexAi/QueryForGoogleCredentials.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/src/EcTranslators/VertexAi/QueryForGoogleCredentials.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.cs b/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.cs new file mode 100644 index 00000000..96c85cff --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.cs @@ -0,0 +1,315 @@ +// #define encryptingNewCredentials + +using System; +using System.Windows.Forms; +using ECInterfaces; // for IEncConverter +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using static SilEncConverters40.EcTranslators.VertexAi.VertexAiEncConverter; +using System.Net; +using SilEncConverters40.EcTranslators.Properties; +using SilEncConverters40.EcTranslators.GoogleTranslator; + +namespace SilEncConverters40.EcTranslators.VertexAi +{ + public partial class VertexAiAutoConfigDialog : AutoConfigDialog + { + private const string SourceLanguageNameMustBeConfigured = ""; + private const string TargetLanguageNameMustBeConfigured = ""; + private readonly string ResourceNeededWarning = $"The {VertexAiEncConverter.strDisplayName} requires an Google Cloud Vertex AI resource."; + + public VertexAiAutoConfigDialog + ( + IEncConverters aECs, + string strDisplayName, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strLhsEncodingId, + string strRhsEncodingId, + int lProcessTypeFlags, + bool bIsInRepository + ) + { + Util.DebugWriteLine(this, "(1) BEGIN"); + InitializeComponent(); + Util.DebugWriteLine(this, "initialized component"); + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + + base.Initialize + ( + aECs, + strHtmlFilename, + strDisplayName, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strLhsEncodingId, + strRhsEncodingId, + lProcessTypeFlags, + bIsInRepository + ); + Util.DebugWriteLine(this, "called base.Initalize"); + + string fromLanguage = SourceLanguageNameMustBeConfigured, toLanguage = TargetLanguageNameMustBeConfigured; + + // if we're editing converter, then set the Converter Spec and say it's unmodified + if (m_bEditMode) + { + System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(ConverterIdentifier)); + + ParseConverterIdentifier(ConverterIdentifier, out fromLanguage, out toLanguage, + out string projectId, out string locationId, out string publisher, out string modelId, + out string addlInstructions, out string systemPrompt); + + textBoxProjectId.Text = projectId; + textBoxLocationId.Text = locationId; + textBoxPublisher.Text = publisher; + textBoxModelId.Text = modelId; + textBoxCompleteSystemPrompt.Text = systemPrompt; + if (!String.IsNullOrEmpty(addlInstructions)) + comboBoxSystemPromptAdditions.Text = addlInstructions; + IsModified = false; + } + else + { + textBoxCompleteSystemPrompt.Text = ResourceNeededWarning; + textBoxProjectId.Text = Settings.Default.GoogleCloudVertexAiProjectId; + textBoxLocationId.Text = Settings.Default.GoogleCloudVertexAiLocationId; + textBoxPublisher.Text = Settings.Default.GoogleCloudVertexAiPublisher; + textBoxModelId.Text = Settings.Default.GoogleCloudVertexAiModelId; + } + + textBoxSourceLanguage.Text = fromLanguage; + textBoxTargetLanguage.Text = toLanguage; + LoadComboBoxFromSettings(comboBoxSystemPromptAdditions, Settings.Default.AzureOpenAiSystemPromptAdditions); + + m_bInitialized = true; + + helpProvider.SetHelpString(textBoxProjectId, Resources.HelpForVertexAiProjectIdTextBox); + helpProvider.SetHelpString(textBoxLocationId, Resources.HelpForVertexAiLocationIdTextBox); + helpProvider.SetHelpString(textBoxPublisher, Resources.HelpForVertexAiPublisherTextBox); + helpProvider.SetHelpString(textBoxModelId, Resources.HelpForVertexAiModelIdTextBox); + helpProvider.SetHelpString(textBoxSourceLanguage, Properties.Resources.HelpForVertexAiSourceLanguageTextBox); + helpProvider.SetHelpString(textBoxTargetLanguage, Properties.Resources.HelpForVertexAiTargetLanguageTextBox); + helpProvider.SetHelpString(textBoxCompleteSystemPrompt, Properties.Resources.HelpForVertexAiSystemPromptTextBox); + helpProvider.SetHelpString(comboBoxSystemPromptAdditions, Properties.Resources.HelpForVertexAiSystemPromptAdditionsComboBox); + helpProvider.SetHelpString(buttonSetVertexAiApiKey, Properties.Resources.HelpForVertexAiAddYourOwnApiKey); + + Util.DebugWriteLine(this, "END"); + } + + private void InitializeComboBoxFromCode(ComboBox comboBox, string code) + { + if (String.IsNullOrEmpty(code)) + return; + + string value = $"({code})"; + var item = comboBox.Items.Cast().FirstOrDefault(i => i.Contains(value)); + + if ((item == null) && (comboBox.Items.Count > 0)) + { + item = (string)comboBox.Items[0]; + } + + if (item != null) + comboBox.SelectedItem = item; + } + + public VertexAiAutoConfigDialog + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + Util.DebugWriteLine(this, "(2) BEGIN"); + InitializeComponent(); + + base.Initialize + ( + aECs, + strFriendlyName, + strConverterIdentifier, + eConversionType, + strTestData + ); + Util.DebugWriteLine(this, "END"); + } + + // this method is called either when the user clicks the "Apply" or "OK" buttons *OR* if she + // tries to switch to the Test or Advanced tab. This is the dialog's one opportunity + // to make sure that the user has correctly configured a legitimate converter. + protected override bool OnApply() + { + if (!IsModified) + return true; + + var additionToSystemPrompt = comboBoxSystemPromptAdditions.Text?.Trim().Replace(";", null); + if (!String.IsNullOrEmpty(additionToSystemPrompt) && !Settings.Default.AzureOpenAiSystemPromptAdditions.Contains(additionToSystemPrompt)) + { + Settings.Default.AzureOpenAiSystemPromptAdditions.Insert(0, additionToSystemPrompt); + Settings.Default.Save(); + } + + var projectId = textBoxProjectId.Text; + var locationId = textBoxLocationId.Text; + var publisher = textBoxPublisher.Text; + var modelId = textBoxModelId.Text; + + if (!IsValidUserInput(null, ref projectId)) + { + MessageBox.Show(this, $"The Vertex AI resource Project Id must be entered and cannot contain a ';' character! See {Resources.GoogleCloudVertexCredentialsDialogInstructionUrl} for help on creating one.", EncConverters.cstrCaption); + return false; + } + Settings.Default.GoogleCloudVertexAiProjectId = projectId; + + if (!IsValidUserInput(null, ref locationId)) + { + MessageBox.Show(this, $"The Vertex AI resource Location Id (e.g. us-central1) must be entered and cannot contain a ';' character! See {Resources.GoogleCloudVertexCredentialsDialogInstructionUrl} for help on creating one.", EncConverters.cstrCaption); + return false; + } + Settings.Default.GoogleCloudVertexAiLocationId = locationId; + + if (!IsValidUserInput(null, ref publisher)) + { + MessageBox.Show(this, $"The Vertex AI resource Publisher (e.g. google) must be entered and cannot contain a ';' character! See {Resources.GoogleCloudVertexCredentialsDialogInstructionUrl} for help on creating one.", EncConverters.cstrCaption); + return false; + } + Settings.Default.GoogleCloudVertexAiPublisher = publisher; + + if (!IsValidUserInput(null, ref modelId)) + { + MessageBox.Show(this, $"The Vertex AI resource Model Id (e.g. chat-bison, chat-bison-32k, or gemini-pro) must be entered and cannot contain a ';' character! See {Resources.GoogleCloudVertexCredentialsDialogInstructionUrl} for help on creating one.", EncConverters.cstrCaption); + return false; + } + Settings.Default.GoogleCloudVertexAiModelId = modelId; + Settings.Default.Save(); + + var selectedFromLanguage = textBoxSourceLanguage.Text; + var selectedToLanguage = textBoxTargetLanguage.Text; + if (!additionToSystemPrompt.StartsWith(ReplacementSystemPrompt)) + { + if (!IsValidUserInput(SourceLanguageNameMustBeConfigured, ref selectedFromLanguage)) + { + MessageBox.Show(this, "A Source language name (e.g. Hindi) must be entered and cannot contain a ';' character!", EncConverters.cstrCaption); + return false; + } + + if (!IsValidUserInput(TargetLanguageNameMustBeConfigured, ref selectedToLanguage)) + { + MessageBox.Show(this, "A Target Language (e.g. English) must be entered and cannot contain a ';' character!", EncConverters.cstrCaption); + return false; + } + } + else + { + selectedFromLanguage = null; + selectedToLanguage = null; + } + + // for Azure Open AI, get the converter identifier from the Setup tab controls. + // e.g. "Hindi;English;with a 'free translation' style aimed at high school students" + ConverterIdentifier = String.Format("{0};{1};{2};{3};{4};{5};{6}", + selectedFromLanguage, + selectedToLanguage, + projectId, + locationId, + publisher, + modelId, + additionToSystemPrompt); + + return base.OnApply(); + + static bool IsValidUserInput(string defaultValue, ref string userInput) + { + userInput = userInput?.Trim(); + return (defaultValue != userInput) && !String.IsNullOrEmpty(userInput) && !userInput.Contains(";"); + } + } + + protected override string ProgID + { + get + { + return typeof(VertexAiEncConverter).FullName; + } + } + + protected override string ImplType + { + get + { + return EncConverters.strTypeSILVertexAiTranslator; + } + } + + protected override string DefaultFriendlyName + { + // as the default, make it the same as the table name (w/o extension) + get + { + var additionToSystemPrompt = comboBoxSystemPromptAdditions.Text?.Trim().Replace(";", null); + if (additionToSystemPrompt.StartsWith(ReplacementSystemPrompt)) + return $"Vertex AI {SubstituteSystemPrompt(additionToSystemPrompt)}"; + + var selectedFromLanguage = textBoxSourceLanguage.Text.Trim(); + if (selectedFromLanguage == SourceLanguageNameMustBeConfigured) + selectedFromLanguage = null; + var selectedToLanguage = textBoxTargetLanguage.Text.Trim(); + if (selectedToLanguage == TargetLanguageNameMustBeConfigured) + selectedToLanguage = null; + return $"Vertex AI Translate {selectedFromLanguage} to {selectedToLanguage}"; + } + } + + private void textBox_TextChanged(object sender, EventArgs e) + { + if (m_bInitialized) // but only do this after we've already initialized (we might have set it during m_bEditMode) + IsModified = true; + UpdateSystemPrompt(); + } + + private void comboBoxSystemPromptAdditions_TextChanged(object sender, EventArgs e) + { + if (m_bInitialized) + IsModified = true; + UpdateSystemPrompt(); + } + + private void UpdateSystemPrompt() + { + var systemPrompt = VertexAiEncConverter.GetSystemPrompt(textBoxSourceLanguage.Text?.Trim(), textBoxTargetLanguage.Text?.Trim(), + comboBoxSystemPromptAdditions.Text?.Trim()); + textBoxCompleteSystemPrompt.Text = systemPrompt; + } + + private void ButtonSetVertexAiKey_Click(object sender, EventArgs e) + { +#if encryptingNewCredentials + var googleTranslatorKeyHide = Properties.Settings.Default.GoogleTranslatorCredentials; + var credentials = EncryptionClass.Encrypt(googleTranslatorKeyHide); +#endif + // only send the key if it's already the override key (so we don't expose ours) + var vertexAiCredentialsOverride = Properties.Settings.Default.GoogleCloudVertexAiCredentialsOverride; + if (!String.IsNullOrEmpty(vertexAiCredentialsOverride)) + vertexAiCredentialsOverride = EncryptionClass.Decrypt(vertexAiCredentialsOverride); + + using var dlg = new QueryForGoogleCredentials(vertexAiCredentialsOverride); + if (dlg.ShowDialog() == DialogResult.OK) + { + GoogleCloudVertexAiSubscriptionKey = dlg.TranslatorKey; + Properties.Settings.Default.Save(); + } + } + + private void TextBoxVertexResourceParameters_TextChanged(object sender, EventArgs e) + { + IsModified = true; + } + } +} + diff --git a/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.designer.cs b/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.designer.cs new file mode 100644 index 00000000..1f7aa6f5 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.designer.cs @@ -0,0 +1,322 @@ +using System; +using ECInterfaces; // for Util + +namespace SilEncConverters40.EcTranslators.VertexAi +{ + partial class VertexAiAutoConfigDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelSourceLanguage = new System.Windows.Forms.Label(); + this.labelTargetLanguage = new System.Windows.Forms.Label(); + this.labelSystemPromptAddition = new System.Windows.Forms.Label(); + this.comboBoxSystemPromptAdditions = new System.Windows.Forms.ComboBox(); + this.buttonSetVertexAiApiKey = new System.Windows.Forms.Button(); + this.textBoxSourceLanguage = new System.Windows.Forms.TextBox(); + this.textBoxTargetLanguage = new System.Windows.Forms.TextBox(); + this.labelSystemPrompt = new System.Windows.Forms.Label(); + this.textBoxCompleteSystemPrompt = new System.Windows.Forms.TextBox(); + this.labelProjectId = new System.Windows.Forms.Label(); + this.textBoxProjectId = new System.Windows.Forms.TextBox(); + this.labelLocationId = new System.Windows.Forms.Label(); + this.textBoxLocationId = new System.Windows.Forms.TextBox(); + this.labelPublisher = new System.Windows.Forms.Label(); + this.textBoxPublisher = new System.Windows.Forms.TextBox(); + this.labelModelId = new System.Windows.Forms.Label(); + this.textBoxModelId = new System.Windows.Forms.TextBox(); + this.tabControl.SuspendLayout(); + this.tabPageSetup.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tabPageSetup + // + this.tabPageSetup.Controls.Add(this.tableLayoutPanel1); + // + // buttonApply + // + this.helpProvider.SetHelpString(this.buttonApply, "Click this button to apply the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonApply, true); + // + // buttonCancel + // + this.helpProvider.SetHelpString(this.buttonCancel, "Click this button to cancel this dialog"); + this.helpProvider.SetShowHelp(this.buttonCancel, true); + // + // buttonOK + // + this.helpProvider.SetHelpString(this.buttonOK, "Click this button to accept the configured values for this converter"); + this.helpProvider.SetShowHelp(this.buttonOK, true); + // + // buttonSaveInRepository + // + this.helpProvider.SetHelpString(this.buttonSaveInRepository, "\r\nClick to add this converter to the system repository permanently.\r\n "); + this.helpProvider.SetShowHelp(this.buttonSaveInRepository, true); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.labelProjectId, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.textBoxProjectId, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.labelLocationId, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.textBoxLocationId, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.labelPublisher, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.textBoxPublisher, 1, 2); + this.tableLayoutPanel1.Controls.Add(this.labelModelId, 0, 3); + this.tableLayoutPanel1.Controls.Add(this.textBoxModelId, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.labelSourceLanguage, 0, 4); + this.tableLayoutPanel1.Controls.Add(this.textBoxSourceLanguage, 1, 4); + this.tableLayoutPanel1.Controls.Add(this.labelTargetLanguage, 0, 5); + this.tableLayoutPanel1.Controls.Add(this.textBoxTargetLanguage, 1, 5); + this.tableLayoutPanel1.Controls.Add(this.labelSystemPromptAddition, 0, 6); + this.tableLayoutPanel1.Controls.Add(this.comboBoxSystemPromptAdditions, 1, 6); + this.tableLayoutPanel1.Controls.Add(this.labelSystemPrompt, 0, 7); + this.tableLayoutPanel1.Controls.Add(this.textBoxCompleteSystemPrompt, 1, 7); + this.tableLayoutPanel1.Controls.Add(this.buttonSetVertexAiApiKey, 1, 8); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 9; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(596, 394); + this.tableLayoutPanel1.TabIndex = 1; + // + // labelSourceLanguage + // + this.labelSourceLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelSourceLanguage.AutoSize = true; + this.labelSourceLanguage.Location = new System.Drawing.Point(47, 173); + this.labelSourceLanguage.Name = "labelSourceLanguage"; + this.labelSourceLanguage.Size = new System.Drawing.Size(91, 13); + this.labelSourceLanguage.TabIndex = 6; + this.labelSourceLanguage.Text = "Source language:"; + // + // labelTargetLanguage + // + this.labelTargetLanguage.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelTargetLanguage.AutoSize = true; + this.labelTargetLanguage.Location = new System.Drawing.Point(50, 213); + this.labelTargetLanguage.Name = "labelTargetLanguage"; + this.labelTargetLanguage.Size = new System.Drawing.Size(88, 13); + this.labelTargetLanguage.TabIndex = 8; + this.labelTargetLanguage.Text = "Target language:"; + // + // labelSystemPromptAddition + // + this.labelSystemPromptAddition.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelSystemPromptAddition.AutoSize = true; + this.labelSystemPromptAddition.Location = new System.Drawing.Point(3, 253); + this.labelSystemPromptAddition.Name = "labelSystemPromptAddition"; + this.labelSystemPromptAddition.Size = new System.Drawing.Size(135, 13); + this.labelSystemPromptAddition.TabIndex = 12; + this.labelSystemPromptAddition.Text = "Additions to system prompt:"; + // + // comboBoxSystemPromptAdditions + // + this.comboBoxSystemPromptAdditions.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.comboBoxSystemPromptAdditions.FormattingEnabled = true; + this.comboBoxSystemPromptAdditions.Location = new System.Drawing.Point(144, 249); + this.comboBoxSystemPromptAdditions.Name = "comboBoxSystemPromptAdditions"; + this.comboBoxSystemPromptAdditions.Size = new System.Drawing.Size(449, 21); + this.comboBoxSystemPromptAdditions.TabIndex = 3; + this.comboBoxSystemPromptAdditions.TextChanged += new System.EventHandler(this.comboBoxSystemPromptAdditions_TextChanged); + // + // buttonSetVertexAiApiKey + // + this.buttonSetVertexAiApiKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.buttonSetVertexAiApiKey.Location = new System.Drawing.Point(144, 368); + this.buttonSetVertexAiApiKey.Name = "buttonSetVertexAiApiKey"; + this.buttonSetVertexAiApiKey.Size = new System.Drawing.Size(326, 23); + this.buttonSetVertexAiApiKey.TabIndex = 5; + this.buttonSetVertexAiApiKey.Text = "Enter your GoogleCloud Vertex AI Credentials (json)"; + this.buttonSetVertexAiApiKey.UseVisualStyleBackColor = true; + this.buttonSetVertexAiApiKey.Click += new System.EventHandler(this.ButtonSetVertexAiKey_Click); + // + // textBoxSourceLanguage + // + this.textBoxSourceLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxSourceLanguage.Location = new System.Drawing.Point(144, 170); + this.textBoxSourceLanguage.Name = "textBoxSourceLanguage"; + this.textBoxSourceLanguage.Size = new System.Drawing.Size(449, 20); + this.textBoxSourceLanguage.TabIndex = 1; + this.textBoxSourceLanguage.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // textBoxTargetLanguage + // + this.textBoxTargetLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxTargetLanguage.Location = new System.Drawing.Point(144, 210); + this.textBoxTargetLanguage.Name = "textBoxTargetLanguage"; + this.textBoxTargetLanguage.Size = new System.Drawing.Size(449, 20); + this.textBoxTargetLanguage.TabIndex = 2; + this.textBoxTargetLanguage.TextChanged += new System.EventHandler(this.textBox_TextChanged); + // + // labelSystemPrompt + // + this.labelSystemPrompt.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelSystemPrompt.AutoSize = true; + this.labelSystemPrompt.Location = new System.Drawing.Point(59, 316); + this.labelSystemPrompt.Name = "labelSystemPrompt"; + this.labelSystemPrompt.Size = new System.Drawing.Size(79, 13); + this.labelSystemPrompt.TabIndex = 12; + this.labelSystemPrompt.Text = "System prompt:"; + // + // textBoxCompleteSystemPrompt + // + this.textBoxCompleteSystemPrompt.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBoxCompleteSystemPrompt.Location = new System.Drawing.Point(144, 283); + this.textBoxCompleteSystemPrompt.Multiline = true; + this.textBoxCompleteSystemPrompt.Name = "textBoxCompleteSystemPrompt"; + this.textBoxCompleteSystemPrompt.ReadOnly = true; + this.textBoxCompleteSystemPrompt.Size = new System.Drawing.Size(449, 79); + this.textBoxCompleteSystemPrompt.TabIndex = 3; + // + // labelProjectId + // + this.labelProjectId.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelProjectId.AutoSize = true; + this.labelProjectId.Location = new System.Drawing.Point(83, 13); + this.labelProjectId.Name = "labelProjectId"; + this.labelProjectId.Size = new System.Drawing.Size(55, 13); + this.labelProjectId.TabIndex = 6; + this.labelProjectId.Text = "Project Id:"; + // + // textBoxProjectId + // + this.textBoxProjectId.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxProjectId.Location = new System.Drawing.Point(144, 10); + this.textBoxProjectId.Name = "textBoxProjectId"; + this.textBoxProjectId.Size = new System.Drawing.Size(449, 20); + this.textBoxProjectId.TabIndex = 1; + this.textBoxProjectId.TextChanged += new System.EventHandler(this.TextBoxVertexResourceParameters_TextChanged); + // + // labelLocationId + // + this.labelLocationId.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelLocationId.AutoSize = true; + this.labelLocationId.Location = new System.Drawing.Point(75, 53); + this.labelLocationId.Name = "labelLocationId"; + this.labelLocationId.Size = new System.Drawing.Size(63, 13); + this.labelLocationId.TabIndex = 6; + this.labelLocationId.Text = "Location Id:"; + // + // textBoxLocationId + // + this.textBoxLocationId.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxLocationId.Location = new System.Drawing.Point(144, 50); + this.textBoxLocationId.Name = "textBoxLocationId"; + this.textBoxLocationId.Size = new System.Drawing.Size(449, 20); + this.textBoxLocationId.TabIndex = 1; + this.textBoxLocationId.TextChanged += new System.EventHandler(this.TextBoxVertexResourceParameters_TextChanged); + // + // labelPublisher + // + this.labelPublisher.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelPublisher.AutoSize = true; + this.labelPublisher.Location = new System.Drawing.Point(85, 93); + this.labelPublisher.Name = "labelPublisher"; + this.labelPublisher.Size = new System.Drawing.Size(53, 13); + this.labelPublisher.TabIndex = 6; + this.labelPublisher.Text = "Publisher:"; + // + // textBoxPublisher + // + this.textBoxPublisher.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxPublisher.Location = new System.Drawing.Point(144, 90); + this.textBoxPublisher.Name = "textBoxPublisher"; + this.textBoxPublisher.Size = new System.Drawing.Size(449, 20); + this.textBoxPublisher.TabIndex = 1; + this.textBoxPublisher.TextChanged += new System.EventHandler(this.TextBoxVertexResourceParameters_TextChanged); + // + // labelModelId + // + this.labelModelId.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.labelModelId.AutoSize = true; + this.labelModelId.Location = new System.Drawing.Point(87, 133); + this.labelModelId.Name = "labelModelId"; + this.labelModelId.Size = new System.Drawing.Size(51, 13); + this.labelModelId.TabIndex = 6; + this.labelModelId.Text = "Model Id:"; + // + // textBoxModelId + // + this.textBoxModelId.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxModelId.Location = new System.Drawing.Point(144, 130); + this.textBoxModelId.Name = "textBoxModelId"; + this.textBoxModelId.Size = new System.Drawing.Size(449, 20); + this.textBoxModelId.TabIndex = 1; + this.textBoxModelId.TextChanged += new System.EventHandler(this.TextBoxVertexResourceParameters_TextChanged); + // + // VertexAiAutoConfigDialog + // + this.ClientSize = new System.Drawing.Size(634, 479); + this.Name = "VertexAiAutoConfigDialog"; + this.Controls.SetChildIndex(this.tabControl, 0); + this.Controls.SetChildIndex(this.buttonApply, 0); + this.Controls.SetChildIndex(this.buttonCancel, 0); + this.Controls.SetChildIndex(this.buttonOK, 0); + this.Controls.SetChildIndex(this.buttonSaveInRepository, 0); + this.tabControl.ResumeLayout(false); + this.tabPageSetup.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label labelSourceLanguage; + private System.Windows.Forms.Label labelTargetLanguage; + private System.Windows.Forms.Label labelSystemPromptAddition; + private System.Windows.Forms.ComboBox comboBoxSystemPromptAdditions; + private System.Windows.Forms.Button buttonSetVertexAiApiKey; + private System.Windows.Forms.TextBox textBoxSourceLanguage; + private System.Windows.Forms.TextBox textBoxTargetLanguage; + private System.Windows.Forms.Label labelSystemPrompt; + private System.Windows.Forms.TextBox textBoxCompleteSystemPrompt; + private System.Windows.Forms.Label labelProjectId; + private System.Windows.Forms.TextBox textBoxProjectId; + private System.Windows.Forms.Label labelLocationId; + private System.Windows.Forms.TextBox textBoxLocationId; + private System.Windows.Forms.Label labelPublisher; + private System.Windows.Forms.TextBox textBoxPublisher; + private System.Windows.Forms.Label labelModelId; + private System.Windows.Forms.TextBox textBoxModelId; + } +} diff --git a/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.resx b/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.resx new file mode 100644 index 00000000..4c464bdd --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiAutoConfigDialog.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 17, 17 + + + 338, 17 + + \ No newline at end of file diff --git a/src/EcTranslators/VertexAi/VertexAiEncConverter.cs b/src/EcTranslators/VertexAi/VertexAiEncConverter.cs new file mode 100644 index 00000000..a2818c1b --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiEncConverter.cs @@ -0,0 +1,252 @@ +// #define encryptingNewCredentials + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Text; +using System.Text.RegularExpressions; +using Microsoft.Win32; // for RegistryKey +using ECInterfaces; // for IEncConverter +using SilEncConverters40.EcTranslators.BingTranslator; +using System.Windows.Forms; +using System.Reflection; +using Google.Apis.Discovery; + +namespace SilEncConverters40.EcTranslators.VertexAi +{ + /// + /// Access to chat-bison or eventually gemini-pro via Google Cloud's Vertext AI + /// +#if X64 + [GuidAttribute("06907915-F41E-48BA-BF47-49F1E3CE584D")] +#else + [GuidAttribute("8B8FC565-9E65-44F7-B2C4-A2C11E54AD86")] +#endif + public class VertexAiEncConverter : PromptExeTranslator + { + #region Member Variable Definitions + protected string VertexAiSystemPrompt; + + public const string strDisplayName = "Vertex AI Translator"; + const string SystemPromptFormat = "You will be given 1 or more lines of text in {0} which you are to translate into {1}{2} and return only the translated lines."; + public static readonly string strHtmlFilename = "Vertex_AI_Translate_Plug-in_About_box.htm"; + public const string strExeDefPath = "VertexAiExe"; + public const string ImplTypeSilVertexAi = "SIL.VertexAi"; + public const string ReplacementSystemPrompt = "UseSystemPrompt: "; // to allow the user to specify the entire system prompt (rather than just the additional bit beyond 'SystemPromptFormat' above + + public const string EnvVarNameProjectId = "EncConverters_VertexAiProjectId"; // e.g. bright-coyote-381812 + public const string EnvVarNameLocationId = "EncConverters_VertexAiLocationId"; // e.g. us-central1 + public const string EnvVarNamePublisher = "EncConverters_VertexAiPublisher"; // e.g. google + public const string EnvVarNameModelId = "EncConverters_VertexAiModelId"; // e.g. chat-bison-32k, chat-bison, gemini-pro, etc. + + #endregion Member Variable Definitions + + #region Initialization + // by putting the google cloud vertex AI credentials in a settings file, users can get their own credentials to use, + // and enter it thru the UI if our key runs out of free stuff + // see https://console.cloud.google.com/apis/credentials + public static string GoogleCloudVertexAiSubscriptionKey + { + get + { + var overrideKey = Properties.Settings.Default.GoogleCloudVertexAiCredentialsOverride; + var key = (!String.IsNullOrEmpty(overrideKey)) + ? overrideKey + : Properties.Settings.Default.GoogleCloudVertexAiCredentials; + +#if encryptingNewCredentials + var translatorKey = EncryptionClass.Encrypt(key); +#endif + return String.IsNullOrEmpty(key) ? key : EncryptionClass.Decrypt(key); // it may be null if the user already has the proper env var + } + set + { + // the value is already encrypted by the time it gets here + var credentials = String.IsNullOrEmpty(value) ? value : EncryptionClass.Encrypt(value); + Properties.Settings.Default.GoogleCloudVertexAiCredentialsOverride = credentials; + } + } + + /// + /// The class constructor. + public VertexAiEncConverter() + : base + ( + typeof(VertexAiEncConverter).FullName, + ImplTypeSilVertexAi + ) + { + } + + public override void Initialize( + string converterName, + string converterSpec, + ref string lhsEncodingID, + ref string rhsEncodingID, + ref ConvType conversionType, + ref Int32 processTypeFlags, + Int32 codePageInput, + Int32 codePageOutput, + bool bAdding) + { + // let the base class have first stab at it + base.Initialize(converterName, converterSpec, ref lhsEncodingID, ref rhsEncodingID, + ref conversionType, ref processTypeFlags, codePageInput, codePageOutput, bAdding); + + ParseConverterIdentifier(converterSpec, out string fromLanguage, out string toLanguage, + out string projectId, out string locationId, out string publisher, out string modelId, + out string addlInstructions, out string systemPrompt); + + VertexAiSystemPrompt = systemPrompt; + + // this is the only one we support from now on (if the user really wants to do legacy to unicode, they have to deal with the legacy as coming in utf-8 format + conversionType = ConvType.Unicode_to_Unicode; + + // I'm assuming that we'd have to/want to set up a different one to go the other direction + m_eConversionType = conversionType = MakeUniDirectional(conversionType); + + if (String.IsNullOrEmpty(lhsEncodingID)) + lhsEncodingID = m_strLhsEncodingID = EncConverters.strDefUnicodeEncoding; + if (String.IsNullOrEmpty(rhsEncodingID)) + rhsEncodingID = m_strRhsEncodingID = EncConverters.strDefUnicodeEncoding; + + // this is a Translation process type by definition. This is used by various programs to prevent + // over usage -- e.g. Paratext should be blocking these EncConverter types as the 'Transliteration' + // type project EncConverter (bkz it'll try to "transliterate" the entire corpus -- probably not + // what's wanted). Also ClipboardEncConverter also doesn't process these for a preview (so the + // system tray popup doesn't take forever to display. + processTypeFlags |= (int)ProcessTypeFlags.Translation; + } + + internal static bool ParseConverterIdentifier(string converterSpec, + out string fromLanguage, out string toLanguage, + out string projectId, out string locationId, out string publisher, out string modelId, + out string addlInstructions, out string systemPrompt) + { + var strs = converterSpec.Split(new[] { ';' }); + if (strs.Length < 6) + throw new ApplicationException($"{strDisplayName} not properly configured! converterSpec: {converterSpec} must have at least a source and target language, followed by GoogleCloud Vertex AI settings: 'projectId', 'locationId' (e.g. us-central1), 'publisher' (e.g. google), and modelId (eg. chat-bison, chat-bison-32k, gemini-pro)"); + + fromLanguage = strs[0]; + toLanguage = strs[1]; + projectId = strs[2]; + locationId = strs[3]; + publisher = strs[4]; + modelId = strs[5]; + + addlInstructions = (strs.Length == 7) + ? strs[6] + : String.Empty; + + systemPrompt = GetSystemPrompt(fromLanguage, toLanguage, addlInstructions); + + return true; + } + + public static string GetSystemPrompt(string fromLanguage, string toLanguage, string addlInstructions) + { + return (addlInstructions.StartsWith(ReplacementSystemPrompt)) + ? SubstituteSystemPrompt(addlInstructions) + : FormatSystemPrompt(fromLanguage, toLanguage, addlInstructions); + } + + public static string SubstituteSystemPrompt(string addlInstructions) + { + return addlInstructions.Substring(ReplacementSystemPrompt.Length).Replace(";", null); + } + + public static string FormatSystemPrompt(string fromLanguage, string toLanguage, string addlInstructions) + { + // can't have double quotes in it, bkz we pass it as a command line parameter surrounded by double quotes + return String.Format(SystemPromptFormat, fromLanguage, toLanguage, $" {addlInstructions.Replace(";", null)}"); + } + + #endregion Initialization + + public override string ExeName + { + get + { + // the requirement is that this DLL (i.e. EcTranslators.dll) is in the same folder as the VertexAiExe.exe + // console app (bkz this EncConverter could be being launched by Paratext, which could even be using a different + // version of the core SilEncConverters40.dll--in its install folder), and which wouldn't have this + // EcTranslators DLL, OR by Word, which knows nothing about either and launches them via COM). + // So to get the path where the VertexAiExe is located, it should be the same location as this DLL + // (e.g. the SILConverters install dir) + var pathToDll = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + return Path.Combine(pathToDll, $"{strExeDefPath}.exe"); + } + } + + public override string Arguments + { + get + { + ParseConverterIdentifier(ConverterIdentifier, out string fromLanguage, out string toLanguage, + out string projectId, out string locationId, out string publisher, out string modelId, + out string addlInstructions, out string systemPrompt); + + var args = new VertexAiPromptExeTranslatorCommandLineArgs + { + ProjectId = projectId, + LocationId = locationId, + Publisher = publisher, + ModelId = modelId, + SystemPrompt = VertexAiSystemPrompt, + Credentials = GoogleCloudVertexAiSubscriptionKey, + ExamplesInputString = ExamplesInputString, + ExamplesOutputString = ExamplesOutputString, + }; + + // The system prompt can't have double quotes in it, bkz those are used for separating the 4 command line parameters, + // So convert them to single quotes, which should also work + // return $"\"{projectId}\" \"{locationId}\" \"{publisher}\" \"{modelId}\" \"{VertexAiSystemPrompt.Replace("\"", "'")}\" \"{GoogleCloudVertexAiSubscriptionKey}\""; + var tempFilespec = args.SaveToTempFile(); + var arguments = $"\"{tempFilespec}\""; + return arguments; + } + } + + private static bool IsValidParameter(string envVarName, ref string parameter) + { + return !string.IsNullOrEmpty(parameter) || + !string.IsNullOrEmpty((parameter = Environment.GetEnvironmentVariable(envVarName))); + } + + #region Misc helpers + + protected override EncodingForm DefaultUnicodeEncForm(bool bForward, bool bLHS) + { + // if it's unspecified, then we want UTF-16 + return EncodingForm.UTF16; + } + + #endregion Misc helpers + + #region Abstract Base Class Overrides + protected override string GetConfigTypeName + { + get { return typeof(VertexAiEncConverterConfig).AssemblyQualifiedName; } + } + + protected override Encoding StandardOutputEncoding + { + get + { + return Encoding.Unicode; + } + } + + protected override Encoding StandardInputEncoding + { + get + { + return Encoding.Unicode; + } + } + + #endregion Abstract Base Class Overrides + } +} + diff --git a/src/EcTranslators/VertexAi/VertexAiEncConverterConfig.cs b/src/EcTranslators/VertexAi/VertexAiEncConverterConfig.cs new file mode 100644 index 00000000..ed08b1ae --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiEncConverterConfig.cs @@ -0,0 +1,65 @@ +using System; +using System.Windows.Forms; +using ECInterfaces; // for IEncConverter + +//uncomment the following line for verbose debugging output using Console.WriteLine +//#define VERBOSE_DEBUGGING + +namespace SilEncConverters40.EcTranslators.VertexAi +{ + public class VertexAiEncConverterConfig : EncConverterConfig + { + public VertexAiEncConverterConfig() + : base + ( + typeof(VertexAiEncConverter).FullName, + VertexAiEncConverter.strDisplayName, + VertexAiEncConverter.strHtmlFilename, + ProcessTypeFlags.Translation + ) + { + } + + [STAThread] + public override bool Configure + ( + IEncConverters aECs, + string strFriendlyName, + ConvType eConversionType, + string strLhsEncodingID, + string strRhsEncodingID + ) + { +#if VERBOSE_DEBUGGING + Console.WriteLine("VertexAiEncConverterConfig(3).Configure BEGIN"); +#endif + VertexAiAutoConfigDialog form = new VertexAiAutoConfigDialog(aECs, m_strDisplayName, m_strFriendlyName, + m_strConverterID, m_eConversionType, m_strLhsEncodingID, m_strRhsEncodingID, + m_lProcessType, m_bIsInRepository); + +#if VERBOSE_DEBUGGING + Console.WriteLine("VertexAiEncConverterConfig.Configure END"); +#endif + return base.Configure(form); + } + + public override void DisplayTestPage + ( + IEncConverters aECs, + string strFriendlyName, + string strConverterIdentifier, + ConvType eConversionType, + string strTestData + ) + { + Console.Error.WriteLine("VertexAiEncConverterConfig.DisplayTestPage() BEGIN"); + InitializeFromThis(ref strFriendlyName, ref strConverterIdentifier, + ref eConversionType, ref strTestData); + + VertexAiAutoConfigDialog form = new VertexAiAutoConfigDialog(aECs, strFriendlyName, + strConverterIdentifier, eConversionType, strTestData); + + base.DisplayTestPage(form); + } + } +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/App.config b/src/EcTranslators/VertexAi/VertexAiExe/App.config new file mode 100644 index 00000000..80bd22f0 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/App.config @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/EcTranslators/VertexAi/VertexAiExe/MessageClasses.cs b/src/EcTranslators/VertexAi/VertexAiExe/MessageClasses.cs new file mode 100644 index 00000000..53023ee0 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/MessageClasses.cs @@ -0,0 +1,43 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SilEncConverters40.EcTranslators.VertexAi.VertexAiExe +{ + public class ChatConversation + { + public string context { get; set; } + public List examples { get; set; } + public List messages { get; set; } + + public override string ToString() + { + return JsonConvert.SerializeObject(this, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore }); + } + } + + public class Example + { + public Input input { get; set; } + public Output output { get; set; } + } + + public class Input + { + public string content { get; set; } + } + + public class Output + { + public string content { get; set; } + } + + public class ChatMessage + { + public string author { get; set; } + public string content { get; set; } + } +} \ No newline at end of file diff --git a/src/EcTranslators/VertexAi/VertexAiExe/Program.cs b/src/EcTranslators/VertexAi/VertexAiExe/Program.cs new file mode 100644 index 00000000..4a6b6962 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/Program.cs @@ -0,0 +1,342 @@ +// #define UseLocalExamples + +#if DEBUG +#define LogResults +#endif + +using Google.Cloud.AIPlatform.V1; +using Google.Protobuf.Collections; +using Google.Protobuf.Reflection; +using Google.Type; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Google.Rpc.Context.AttributeContext.Types; +using Value = Google.Protobuf.WellKnownTypes.Value; + +namespace SilEncConverters40.EcTranslators.VertexAi.VertexAiExe +{ + internal class Program + { +#if LogResults + private const string LogFilePath = @"C:\btmp\VertexAiExeLog.txt"; +#endif + private const string EnvVarNameProjectId = "EncConverters_VertexAiProjectId"; // e.g. bright-coyote-381812 + private const string EnvVarNameLocationId = "EncConverters_VertexAiLocationId"; // e.g. us-central1 + private const string EnvVarNamePublisher = "EncConverters_VertexAiPublisher"; // e.g. google + private const string EnvVarNameModelId = "EncConverters_VertexAiModelId"; // e.g. chat-bison-32k, chat-bison, gemini-pro, etc. + + private const string EnvVarNameGoogleApplicationCredentials = "GOOGLE_APPLICATION_CREDENTIALS"; // e.g. @"C:\Users\pete_\Downloads\bright-coyote-381812-bc584cec007f.json" + + private static readonly char[] TrimmableChars = new char[] { '\r', '\n', ' ' }; + + static async Task Main(string[] args) + { + // set the stdin/out to Unicode + Console.InputEncoding = Encoding.Unicode; + Console.OutputEncoding = Encoding.Unicode; + + string pathToEncryptedCommandLineParameterFile = null; + if ((args.Length == 0) || !File.Exists((pathToEncryptedCommandLineParameterFile = args[0]))) + { + Console.WriteLine(String.Format("Usage:{0}{0}{1} \"\"", Environment.NewLine, typeof(Program).Namespace)); + return; + } + + var credentialFile = String.Empty; + var originalCredentialFileSpec = Environment.GetEnvironmentVariable(EnvVarNameGoogleApplicationCredentials); + var credentialsEnvironmentVariableAlreadySet = !String.IsNullOrEmpty(originalCredentialFileSpec); + try + { + var contents = File.ReadAllText(pathToEncryptedCommandLineParameterFile); + var json = EncryptionClass.Decrypt(contents); + var arguments = JsonConvert.DeserializeObject(json); + + credentialFile = credentialsEnvironmentVariableAlreadySet ? originalCredentialFileSpec : null; + if (!IsValidParameters(arguments, out PredictionServiceClient client, out EndpointName endpointName, ref credentialFile, out string systemPrompt)) + return; + + await ProcessRequest(arguments, client, endpointName, systemPrompt); + } + catch (Exception ex) + { + Console.WriteLine(GetExceptionMessage(ex)); + } + finally + { + if (!credentialsEnvironmentVariableAlreadySet) + { + if (File.Exists(credentialFile)) + File.Delete(credentialFile); + + Environment.SetEnvironmentVariable(EnvVarNameGoogleApplicationCredentials, String.Empty); + } + } + + static string GetExceptionMessage(Exception ex) + { + var message = ex.Message; + var msg = "Error occurred: " + message; + while (ex.InnerException != null) + { + ex = ex.InnerException; + if (message.Contains(ex.Message)) + continue; // skip identical msgs + message = ex.Message; + msg += $"{Environment.NewLine}because: (InnerException): {message}"; + } + return msg; + } + } + + private static async Task ProcessRequest(VertexAiPromptExeTranslatorCommandLineArgs arguments, PredictionServiceClient client, + EndpointName endpointName, string systemPrompt) + { + var chatConversation = new ChatConversation + { + context = $"You are a Language Translator that Translates between different languages. Your job is to translate the text in the user prompt into the requested language according to the following instructions: {systemPrompt}", + examples = new List(), + messages = new List() + }; + + var numberOfExamples = arguments.ExamplesInputString.Count; + for (int i = 0; i < numberOfExamples; i++) + { + chatConversation.examples.Add(new Example + { + input = new Input { content = arguments.ExamplesInputString[i] }, + output = new Output { content = arguments.ExamplesOutputString[i] } + }); + } + + // You can construct Protobuf from JSON. + var parametersJson = JsonConvert.SerializeObject(new + { + temperature = (arguments.Temperature == null) ? 0.3 : (double)arguments.Temperature, + maxDecodeSteps = (arguments.MaxDecodeSteps == null) ? 200 : (int)arguments.MaxDecodeSteps, + topP = (arguments.TopP == null) ? 0.8 : arguments.TopP, + topK = (arguments.TopK == null) ? 40 : arguments.TopK, + }); + var parameters = Value.Parser.ParseJson(parametersJson); + + // in case there are multiple lines (e.g. what Paratext will do if the verse has multiple paragraphs), + // process in a while loop + var index = 0; +#if UseLocalExamples + List input = new List { "उसने सब लोग जान से मारा।", "वहाँ वह विश्राम के दिन प्रार्थना घर में जाकर लोगों को परमेश्वर का वचन सुनाने लगा। सब लोग सुनकर चकित हो गये।", "", "परंतु कई तो यह भी कहने लगे, “यह ज्ञान इसको कहाँ से आया!? और ऐसे सामर्थ्‍य के काम यह कैसे करता है, जिसकी चर्चा सब लोग कर रहे हैं!?" }; +#else + List input = null; // new List { "वहाँ वह विश्राम के दिन प्रार्थना घर में जाकर लोगों को परमेश्वर का वचन सुनाने लगा। सब लोग सुनकर चकित हो गये।", "", "परंतु कई तो यह भी कहने लगे, “यह ज्ञान इसको कहाँ से आया!? और ऐसे सामर्थ्‍य के काम यह कैसे करता है, जिसकी चर्चा सब लोग कर रहे हैं!?" }; +#endif + while ((input != null && input.Count > index) || (input == null && Console.In.Peek() != -1)) + { + var strInput = (input != null) + ? input[index++] + : Console.ReadLine(); + if (String.IsNullOrEmpty(strInput?.Trim(TrimmableChars))) // don't actually trim them, but just for the sake of finding nothing to translate... + continue; + + // add the string to be translated to as the 'user' message + chatConversation.messages.Add(new ChatMessage { author = "user", content = strInput }); + + // call the service to process the user msg based on the given system prompt + // Make the request. + var json = chatConversation.ToString(); +#if LogResults + File.AppendAllText(LogFilePath, json + Environment.NewLine); +#endif + var response = client.Predict(endpointName, new List { Value.Parser.ParseJson(json) }, parameters); + + var fields = response.Predictions.First().StructValue.Fields; + // clean up and return the "assistent's response" + var strOutput = HarvestResult(strInput, fields); + + // put that back in the chat, in case we are processing multiple lines + // (this'll make them 'related' for better translation) + chatConversation.messages.Add(new ChatMessage { author = "1", content = strOutput }); + } + + for (var i = 0; i < chatConversation.messages.Count;) + { + var strInput = chatConversation.messages[i++].content; + var strOutput = chatConversation.messages[i++].content; + +#if LogResults + File.AppendAllText(LogFilePath, string.Format("{1}=>{2}:{3}=>{4}{0}", Environment.NewLine, systemPrompt, i / 2, strInput, strOutput)); +#endif + // write the responses to the standard out to return it + Console.WriteLine(strOutput); + } + + return true; + } + + private static string HarvestResult(string strInput, MapField fields) + { + var responseContent = fields["candidates"].ListValue.Values[0].StructValue.Fields["content"].StringValue; + + if (strInput?[0] != ' ' && responseContent?[0] == ' ') + responseContent = responseContent.Substring(1); + + // these come from: https://cloud.google.com/vertex-ai/docs/generative-ai/configure-safety-attributes-palm + if (responseContent.Contains("I'm not able to help with that, as I'm only a language model. If you believe this is an error, please send us your feedback.")) + { + var blocked = fields["safetyAttributes"].ListValue.Values[0].StructValue.Fields["blocked"].BoolValue; + if (blocked) + { + var errors = fields["safetyAttributes"].ListValue.Values[0].StructValue.Fields["errors"].ListValue.Values[0].NumberValue.ToString(); + if ((errors.Length == 3) && (errors[0] == '2')) + { + string contentFilteringReason = "violence, sexual content, etc."; + switch (errors.Substring(1)) + { + case "20": + contentFilteringReason = "The supplied or returned language is unsupported.For a list of supported languages, see Language support."; + break; + + case "30": + contentFilteringReason = "The prompt or response was blocked because it was found to be potentially harmful. A term is included from the terminology blocklist. Rephrase your prompt."; + break; + + case "31": + contentFilteringReason = "The content might include Sensitive Personally Identifiable Information(SPII). Rephrase your prompt."; + break; + + case "40": + contentFilteringReason = "The prompt or response was blocked because it was found to be potentially harmful. The content violates SafeSearch settings.Rephrase your prompt."; + break; + + case "50": + contentFilteringReason = "The prompt or response was blocked because it might contain sexually explicit content.Rephrase your prompt."; + break; + + case "51": + contentFilteringReason = "The prompt or response was blocked because it might contain hate speech content.Rephrase your prompt."; + break; + + case "52": + contentFilteringReason = "The prompt or response was blocked because it might contain harassment content. Rephrase your prompt."; + break; + + case "53": + contentFilteringReason = "The prompt or response was blocked because it might contain dangerous content. Rephrase your prompt."; + break; + + case "54": + contentFilteringReason = "The prompt or response was blocked because it might contain toxic content. Rephrase your prompt."; + break; + + default: + case "00": + contentFilteringReason = "Reason unknown. Rephrase your prompt."; + break; + } + + responseContent = $""; + } + } + } + + return CleanString(strInput, responseContent); + } + + private static string CleanString(string input, string output) + { + if (!String.IsNullOrEmpty(input) && input.Length > 1) + { + if (input.First() != '"') + output = output.TrimStart('"'); + if (input.Length > 2 && input.Last() != '"') + output = output.TrimEnd('"'); + } + + return output; + } + + private static bool IsValidParameters(VertexAiPromptExeTranslatorCommandLineArgs arguments, out PredictionServiceClient client, + out EndpointName endpoint, ref string credentialFile, out string systemPrompt) + { + client = null; + endpoint = null; + + var projectId = arguments.ProjectId; + var locationId = arguments.LocationId; + var publisher = arguments.Publisher; + var modelId = arguments.ModelId; + + systemPrompt = arguments.SystemPrompt; + + if (String.IsNullOrEmpty(projectId) || String.IsNullOrEmpty(locationId) || String.IsNullOrEmpty(publisher) || String.IsNullOrEmpty(modelId) || String.IsNullOrEmpty(systemPrompt)) + { + Console.WriteLine(String.Format("Usage:{0}{0}{1} \"\"", Environment.NewLine, typeof(Program).Namespace)); + return false; + } + + // only put the credentials in a temp file, if it wasn't already set as an environment variable + string credentials = null; + if (String.IsNullOrEmpty(credentialFile) && !String.IsNullOrEmpty((credentials = arguments.Credentials))) + { + credentialFile = Path.GetTempFileName(); + File.WriteAllText(credentialFile, credentials.Replace("'", "\"")); + + Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", credentialFile); + } + + if (!IsValidParameter(EnvVarNameProjectId, ref projectId)) + { + Console.WriteLine($"The calling program failed to send the GoogleCloud ProjectId (first) command line parameter. You can also pass it by setting the '{EnvVarNameProjectId}' environment variable."); + return false; + } + + if (!IsValidParameter(EnvVarNameLocationId, ref locationId)) + { + Console.WriteLine($"The calling program failed to send the GoogleCloud LocationId (second) command line parameter (where the VertexAI resource is located, e.g. 'us-central1'). You can also pass it by setting the '{EnvVarNameLocationId}' environment variable."); + return false; + } + + if (!IsValidParameter(EnvVarNamePublisher, ref publisher)) + { + Console.WriteLine($"The calling program failed to send the Vertex AI Publisher (third) command line parameter (e.g. 'google'). You can also pass it by setting the '{EnvVarNamePublisher}' environment variable."); + return false; + } + + if (!IsValidParameter(EnvVarNameModelId, ref modelId)) + { + Console.WriteLine($"The calling program failed to send the Vertext AI ModelId (third) command line parameter (e.g. chat-bison-32k, chat-bison, gemini-pro, etc). You can also pass it by setting the '{EnvVarNameModelId}' environment variable."); + return false; + } + + if (String.IsNullOrEmpty(systemPrompt)) + { + Console.WriteLine("The calling program failed to send the System Prompt (forth) command line parameter"); + return false; + } + + client = new PredictionServiceClientBuilder + { + Endpoint = $"{locationId}-aiplatform.googleapis.com" + }.Build(); + + // Configure the parent resource. + endpoint = EndpointName.FromProjectLocationPublisherModel(projectId, locationId, publisher, modelId); + + return true; + } + + private static bool IsValidParameter(string envVarName, ref string parameter) + { + return !string.IsNullOrEmpty(parameter) || + !string.IsNullOrEmpty((parameter = Environment.GetEnvironmentVariable(envVarName))); + } + + static string Base64ToString(string base64String) + { + byte[] base64Bytes = Convert.FromBase64String(base64String); + return Encoding.UTF8.GetString(base64Bytes); + } + } +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/Properties/AssemblyInfo.cs b/src/EcTranslators/VertexAi/VertexAiExe/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..0c93e171 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("VertexAiExe")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("VertexAiExe")] +[assembly: AssemblyCopyright("Copyright © 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5e1021b4-61ae-4e96-8d5a-7cdf6d5f7982")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/EcTranslators/VertexAi/VertexAiExe/VertexAiExe.csproj b/src/EcTranslators/VertexAi/VertexAiExe/VertexAiExe.csproj new file mode 100644 index 00000000..caf7fac4 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/VertexAiExe.csproj @@ -0,0 +1,238 @@ + + + + + Debug + x64 + {5E1021B4-61AE-4E96-8D5A-7CDF6D5F7982} + Exe + SilEncConverters40.EcTranslators.VertexAi.VertexAiExe + VertexAiExe + v4.8 + 512 + true + true + latest + + + + + true + ..\..\..\..\output\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + true + + + ..\..\..\..\output\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + true + + + true + ..\..\..\..\output\Win32\Debug\ + DEBUG;TRACE + full + x86 + prompt + true + + + ..\..\..\..\output\Win32\Release\ + TRACE + true + pdbonly + x86 + prompt + true + + + + ..\..\..\..\packages\Google.Api.CommonProtos.2.13.0\lib\net461\Google.Api.CommonProtos.dll + + + ..\..\..\..\packages\Google.Api.Gax.4.4.0\lib\net462\Google.Api.Gax.dll + + + ..\..\..\..\packages\Google.Api.Gax.Grpc.4.4.0\lib\net462\Google.Api.Gax.Grpc.dll + + + ..\..\..\..\packages\Google.Apis.1.66.0\lib\net462\Google.Apis.dll + + + ..\..\..\..\packages\Google.Apis.Auth.1.66.0\lib\net462\Google.Apis.Auth.dll + + + ..\..\..\..\packages\Google.Apis.Core.1.66.0\lib\net462\Google.Apis.Core.dll + + + ..\..\..\..\packages\Google.Cloud.AIPlatform.V1.2.20.0\lib\net462\Google.Cloud.AIPlatform.V1.dll + + + ..\..\..\..\packages\Google.Cloud.Iam.V1.3.0.0\lib\net462\Google.Cloud.Iam.V1.dll + + + ..\..\..\..\packages\Google.Cloud.Location.2.0.0\lib\net462\Google.Cloud.Location.dll + + + ..\..\..\..\packages\Google.LongRunning.3.0.0\lib\net462\Google.LongRunning.dll + + + ..\..\..\..\packages\Google.Protobuf.3.25.2\lib\net45\Google.Protobuf.dll + + + ..\..\..\..\packages\Grpc.Auth.2.60.0\lib\net462\Grpc.Auth.dll + + + ..\..\..\..\packages\Grpc.Core.2.46.6\lib\net45\Grpc.Core.dll + + + ..\..\..\..\packages\Grpc.Core.Api.2.60.0\lib\net462\Grpc.Core.Api.dll + + + ..\..\..\..\packages\Grpc.Net.Client.2.60.0\lib\net462\Grpc.Net.Client.dll + + + ..\..\..\..\packages\Grpc.Net.Common.2.60.0\lib\netstandard2.0\Grpc.Net.Common.dll + + + ..\..\..\..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\..\..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\..\..\..\packages\Microsoft.Extensions.Logging.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\..\..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + + + ..\..\..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\..\..\..\packages\System.CodeDom.8.0.0\lib\net462\System.CodeDom.dll + + + + ..\..\..\..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + + ..\..\..\..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + ..\..\..\..\packages\System.Net.Http.WinHttpHandler.8.0.0\lib\net462\System.Net.Http.WinHttpHandler.dll + + + + ..\..\..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\..\..\..\packages\System.Runtime.CompilerServices.Unsafe.7.0.0-preview.2.22152.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\..\..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + ..\..\..\..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + + + + + + + + + PromptExeTranslatorCommandLineArgs.cs + + + RsaEncryptionClass.cs + + + VertexAiPromptExeTranslatorCommandLineArgs.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/src/EcTranslators/VertexAi/VertexAiExe/packages.config b/src/EcTranslators/VertexAi/VertexAiExe/packages.config new file mode 100644 index 00000000..7bdaad2f --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/packages.config @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/annotations.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/annotations.proto new file mode 100644 index 00000000..efdab3db --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/annotations.proto @@ -0,0 +1,31 @@ +// Copyright 2015 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/auth.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/auth.proto new file mode 100644 index 00000000..ca91bb1b --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/auth.proto @@ -0,0 +1,237 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "AuthProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Authentication` defines the authentication configuration for API methods +// provided by an API service. +// +// Example: +// +// name: calendar.googleapis.com +// authentication: +// providers: +// - id: google_calendar_auth +// jwks_uri: https://www.googleapis.com/oauth2/v1/certs +// issuer: https://securetoken.google.com +// rules: +// - selector: "*" +// requirements: +// provider_id: google_calendar_auth +// - selector: google.calendar.Delegate +// oauth: +// canonical_scopes: https://www.googleapis.com/auth/calendar.read +message Authentication { + // A list of authentication rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated AuthenticationRule rules = 3; + + // Defines a set of authentication providers that a service supports. + repeated AuthProvider providers = 4; +} + +// Authentication rules for the service. +// +// By default, if a method has any authentication requirements, every request +// must include a valid credential matching one of the requirements. +// It's an error to include more than one kind of credential in a single +// request. +// +// If a method doesn't have any auth requirements, request credentials will be +// ignored. +message AuthenticationRule { + // Selects the methods to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // The requirements for OAuth credentials. + OAuthRequirements oauth = 2; + + // If true, the service accepts API keys without any other credential. + // This flag only applies to HTTP and gRPC requests. + bool allow_without_credential = 5; + + // Requirements for additional authentication providers. + repeated AuthRequirement requirements = 7; +} + +// Specifies a location to extract JWT from an API request. +message JwtLocation { + oneof in { + // Specifies HTTP header name to extract JWT token. + string header = 1; + + // Specifies URL query parameter name to extract JWT token. + string query = 2; + + // Specifies cookie name to extract JWT token. + string cookie = 4; + } + + // The value prefix. The value format is "value_prefix{token}" + // Only applies to "in" header type. Must be empty for "in" query type. + // If not empty, the header value has to match (case sensitive) this prefix. + // If not matched, JWT will not be extracted. If matched, JWT will be + // extracted after the prefix is removed. + // + // For example, for "Authorization: Bearer {JWT}", + // value_prefix="Bearer " with a space at the end. + string value_prefix = 3; +} + +// Configuration for an authentication provider, including support for +// [JSON Web Token +// (JWT)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32). +message AuthProvider { + // The unique identifier of the auth provider. It will be referred to by + // `AuthRequirement.provider_id`. + // + // Example: "bookstore_auth". + string id = 1; + + // Identifies the principal that issued the JWT. See + // https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.1 + // Usually a URL or an email address. + // + // Example: https://securetoken.google.com + // Example: 1234567-compute@developer.gserviceaccount.com + string issuer = 2; + + // URL of the provider's public key set to validate signature of the JWT. See + // [OpenID + // Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). + // Optional if the key set document: + // - can be retrieved from + // [OpenID + // Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) + // of the issuer. + // - can be inferred from the email domain of the issuer (e.g. a Google + // service account). + // + // Example: https://www.googleapis.com/oauth2/v1/certs + string jwks_uri = 3; + + // The list of JWT + // [audiences](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.3). + // that are allowed to access. A JWT containing any of these audiences will + // be accepted. When this setting is absent, JWTs with audiences: + // - "https://[service.name]/[google.protobuf.Api.name]" + // - "https://[service.name]/" + // will be accepted. + // For example, if no audiences are in the setting, LibraryService API will + // accept JWTs with the following audiences: + // - + // https://library-example.googleapis.com/google.example.library.v1.LibraryService + // - https://library-example.googleapis.com/ + // + // Example: + // + // audiences: bookstore_android.apps.googleusercontent.com, + // bookstore_web.apps.googleusercontent.com + string audiences = 4; + + // Redirect URL if JWT token is required but not present or is expired. + // Implement authorizationUrl of securityDefinitions in OpenAPI spec. + string authorization_url = 5; + + // Defines the locations to extract the JWT. For now it is only used by the + // Cloud Endpoints to store the OpenAPI extension [x-google-jwt-locations] + // (https://cloud.google.com/endpoints/docs/openapi/openapi-extensions#x-google-jwt-locations) + // + // JWT locations can be one of HTTP headers, URL query parameters or + // cookies. The rule is that the first match wins. + // + // If not specified, default to use following 3 locations: + // 1) Authorization: Bearer + // 2) x-goog-iap-jwt-assertion + // 3) access_token query parameter + // + // Default locations can be specified as followings: + // jwt_locations: + // - header: Authorization + // value_prefix: "Bearer " + // - header: x-goog-iap-jwt-assertion + // - query: access_token + repeated JwtLocation jwt_locations = 6; +} + +// OAuth scopes are a way to define data and permissions on data. For example, +// there are scopes defined for "Read-only access to Google Calendar" and +// "Access to Cloud Platform". Users can consent to a scope for an application, +// giving it permission to access that data on their behalf. +// +// OAuth scope specifications should be fairly coarse grained; a user will need +// to see and understand the text description of what your scope means. +// +// In most cases: use one or at most two OAuth scopes for an entire family of +// products. If your product has multiple APIs, you should probably be sharing +// the OAuth scope across all of those APIs. +// +// When you need finer grained OAuth consent screens: talk with your product +// management about how developers will use them in practice. +// +// Please note that even though each of the canonical scopes is enough for a +// request to be accepted and passed to the backend, a request can still fail +// due to the backend requiring additional scopes or permissions. +message OAuthRequirements { + // The list of publicly documented OAuth scopes that are allowed access. An + // OAuth token containing any of these scopes will be accepted. + // + // Example: + // + // canonical_scopes: https://www.googleapis.com/auth/calendar, + // https://www.googleapis.com/auth/calendar.read + string canonical_scopes = 1; +} + +// User-defined authentication requirements, including support for +// [JSON Web Token +// (JWT)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32). +message AuthRequirement { + // [id][google.api.AuthProvider.id] from authentication provider. + // + // Example: + // + // provider_id: bookstore_auth + string provider_id = 1; + + // NOTE: This will be deprecated soon, once AuthProvider.audiences is + // implemented and accepted in all the runtime components. + // + // The list of JWT + // [audiences](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32#section-4.1.3). + // that are allowed to access. A JWT containing any of these audiences will + // be accepted. When this setting is absent, only JWTs with audience + // "https://[Service_name][google.api.Service.name]/[API_name][google.protobuf.Api.name]" + // will be accepted. For example, if no audiences are in the setting, + // LibraryService API will only accept JWTs with the following audience + // "https://library-example.googleapis.com/google.example.library.v1.LibraryService". + // + // Example: + // + // audiences: bookstore_android.apps.googleusercontent.com, + // bookstore_web.apps.googleusercontent.com + string audiences = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/backend.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/backend.proto new file mode 100644 index 00000000..6ff68878 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/backend.proto @@ -0,0 +1,185 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "BackendProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Backend` defines the backend configuration for a service. +message Backend { + // A list of API backend rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated BackendRule rules = 1; +} + +// A backend rule provides configuration for an individual API element. +message BackendRule { + // Path Translation specifies how to combine the backend address with the + // request path in order to produce the appropriate forwarding URL for the + // request. + // + // Path Translation is applicable only to HTTP-based backends. Backends which + // do not accept requests over HTTP/HTTPS should leave `path_translation` + // unspecified. + enum PathTranslation { + PATH_TRANSLATION_UNSPECIFIED = 0; + + // Use the backend address as-is, with no modification to the path. If the + // URL pattern contains variables, the variable names and values will be + // appended to the query string. If a query string parameter and a URL + // pattern variable have the same name, this may result in duplicate keys in + // the query string. + // + // # Examples + // + // Given the following operation config: + // + // Method path: /api/company/{cid}/user/{uid} + // Backend address: https://example.cloudfunctions.net/getUser + // + // Requests to the following request paths will call the backend at the + // translated path: + // + // Request path: /api/company/widgetworks/user/johndoe + // Translated: + // https://example.cloudfunctions.net/getUser?cid=widgetworks&uid=johndoe + // + // Request path: /api/company/widgetworks/user/johndoe?timezone=EST + // Translated: + // https://example.cloudfunctions.net/getUser?timezone=EST&cid=widgetworks&uid=johndoe + CONSTANT_ADDRESS = 1; + + // The request path will be appended to the backend address. + // + // # Examples + // + // Given the following operation config: + // + // Method path: /api/company/{cid}/user/{uid} + // Backend address: https://example.appspot.com + // + // Requests to the following request paths will call the backend at the + // translated path: + // + // Request path: /api/company/widgetworks/user/johndoe + // Translated: + // https://example.appspot.com/api/company/widgetworks/user/johndoe + // + // Request path: /api/company/widgetworks/user/johndoe?timezone=EST + // Translated: + // https://example.appspot.com/api/company/widgetworks/user/johndoe?timezone=EST + APPEND_PATH_TO_ADDRESS = 2; + } + + // Selects the methods to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // The address of the API backend. + // + // The scheme is used to determine the backend protocol and security. + // The following schemes are accepted: + // + // SCHEME PROTOCOL SECURITY + // http:// HTTP None + // https:// HTTP TLS + // grpc:// gRPC None + // grpcs:// gRPC TLS + // + // It is recommended to explicitly include a scheme. Leaving out the scheme + // may cause constrasting behaviors across platforms. + // + // If the port is unspecified, the default is: + // - 80 for schemes without TLS + // - 443 for schemes with TLS + // + // For HTTP backends, use [protocol][google.api.BackendRule.protocol] + // to specify the protocol version. + string address = 2; + + // The number of seconds to wait for a response from a request. The default + // varies based on the request protocol and deployment environment. + double deadline = 3; + + // Deprecated, do not use. + double min_deadline = 4 [deprecated = true]; + + // The number of seconds to wait for the completion of a long running + // operation. The default is no deadline. + double operation_deadline = 5; + + PathTranslation path_translation = 6; + + // Authentication settings used by the backend. + // + // These are typically used to provide service management functionality to + // a backend served on a publicly-routable URL. The `authentication` + // details should match the authentication behavior used by the backend. + // + // For example, specifying `jwt_audience` implies that the backend expects + // authentication via a JWT. + // + // When authentication is unspecified, the resulting behavior is the same + // as `disable_auth` set to `true`. + // + // Refer to https://developers.google.com/identity/protocols/OpenIDConnect for + // JWT ID token. + oneof authentication { + // The JWT audience is used when generating a JWT ID token for the backend. + // This ID token will be added in the HTTP "authorization" header, and sent + // to the backend. + string jwt_audience = 7; + + // When disable_auth is true, a JWT ID token won't be generated and the + // original "Authorization" HTTP header will be preserved. If the header is + // used to carry the original token and is expected by the backend, this + // field must be set to true to preserve the header. + bool disable_auth = 8; + } + + // The protocol used for sending a request to the backend. + // The supported values are "http/1.1" and "h2". + // + // The default value is inferred from the scheme in the + // [address][google.api.BackendRule.address] field: + // + // SCHEME PROTOCOL + // http:// http/1.1 + // https:// http/1.1 + // grpc:// h2 + // grpcs:// h2 + // + // For secure HTTP backends (https://) that support HTTP/2, set this field + // to "h2" for improved performance. + // + // Configuring this field to non-default values is only supported for secure + // HTTP backends. This field will be ignored for all other backends. + // + // See + // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids + // for more details on the supported values. + string protocol = 9; + + // The map between request protocol and the backend address. + map overrides_by_request_protocol = 10; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/billing.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/billing.proto new file mode 100644 index 00000000..8b75452f --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/billing.proto @@ -0,0 +1,77 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "BillingProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Billing related configuration of the service. +// +// The following example shows how to configure monitored resources and metrics +// for billing, `consumer_destinations` is the only supported destination and +// the monitored resources need at least one label key +// `cloud.googleapis.com/location` to indicate the location of the billing +// usage, using different monitored resources between monitoring and billing is +// recommended so they can be evolved independently: +// +// +// monitored_resources: +// - type: library.googleapis.com/billing_branch +// labels: +// - key: cloud.googleapis.com/location +// description: | +// Predefined label to support billing location restriction. +// - key: city +// description: | +// Custom label to define the city where the library branch is located +// in. +// - key: name +// description: Custom label to define the name of the library branch. +// metrics: +// - name: library.googleapis.com/book/borrowed_count +// metric_kind: DELTA +// value_type: INT64 +// unit: "1" +// billing: +// consumer_destinations: +// - monitored_resource: library.googleapis.com/billing_branch +// metrics: +// - library.googleapis.com/book/borrowed_count +message Billing { + // Configuration of a specific billing destination (Currently only support + // bill against consumer project). + message BillingDestination { + // The monitored resource type. The type must be defined in + // [Service.monitored_resources][google.api.Service.monitored_resources] + // section. + string monitored_resource = 1; + + // Names of the metrics to report to this billing destination. + // Each name must be defined in + // [Service.metrics][google.api.Service.metrics] section. + repeated string metrics = 2; + } + + // Billing configurations for sending metrics to the consumer project. + // There can be multiple consumer destinations per service, each one must have + // a different monitored resource type. A metric can be used in at most + // one consumer destination. + repeated BillingDestination consumer_destinations = 8; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/client.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/client.proto new file mode 100644 index 00000000..6d01954e --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/client.proto @@ -0,0 +1,394 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/launch_stage.proto"; +import "google/protobuf/descriptor.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "ClientProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // A definition of a client library method signature. + // + // In client libraries, each proto RPC corresponds to one or more methods + // which the end user is able to call, and calls the underlying RPC. + // Normally, this method receives a single argument (a struct or instance + // corresponding to the RPC request object). Defining this field will + // add one or more overloads providing flattened or simpler method signatures + // in some languages. + // + // The fields on the method signature are provided as a comma-separated + // string. + // + // For example, the proto RPC and annotation: + // + // rpc CreateSubscription(CreateSubscriptionRequest) + // returns (Subscription) { + // option (google.api.method_signature) = "name,topic"; + // } + // + // Would add the following Java overload (in addition to the method accepting + // the request object): + // + // public final Subscription createSubscription(String name, String topic) + // + // The following backwards-compatibility guidelines apply: + // + // * Adding this annotation to an unannotated method is backwards + // compatible. + // * Adding this annotation to a method which already has existing + // method signature annotations is backwards compatible if and only if + // the new method signature annotation is last in the sequence. + // * Modifying or removing an existing method signature annotation is + // a breaking change. + // * Re-ordering existing method signature annotations is a breaking + // change. + repeated string method_signature = 1051; +} + +extend google.protobuf.ServiceOptions { + // The hostname for this service. + // This should be specified with no prefix or protocol. + // + // Example: + // + // service Foo { + // option (google.api.default_host) = "foo.googleapi.com"; + // ... + // } + string default_host = 1049; + + // OAuth scopes needed for the client. + // + // Example: + // + // service Foo { + // option (google.api.oauth_scopes) = \ + // "https://www.googleapis.com/auth/cloud-platform"; + // ... + // } + // + // If there is more than one scope, use a comma-separated string: + // + // Example: + // + // service Foo { + // option (google.api.oauth_scopes) = \ + // "https://www.googleapis.com/auth/cloud-platform," + // "https://www.googleapis.com/auth/monitoring"; + // ... + // } + string oauth_scopes = 1050; +} + +// Required information for every language. +message CommonLanguageSettings { + // Link to automatically generated reference documentation. Example: + // https://cloud.google.com/nodejs/docs/reference/asset/latest + string reference_docs_uri = 1 [deprecated = true]; + + // The destination where API teams want this client library to be published. + repeated ClientLibraryDestination destinations = 2; +} + +// Details about how and where to publish client libraries. +message ClientLibrarySettings { + // Version of the API to apply these settings to. This is the full protobuf + // package for the API, ending in the version element. + // Examples: "google.cloud.speech.v1" and "google.spanner.admin.database.v1". + string version = 1; + + // Launch stage of this version of the API. + LaunchStage launch_stage = 2; + + // When using transport=rest, the client request will encode enums as + // numbers rather than strings. + bool rest_numeric_enums = 3; + + // Settings for legacy Java features, supported in the Service YAML. + JavaSettings java_settings = 21; + + // Settings for C++ client libraries. + CppSettings cpp_settings = 22; + + // Settings for PHP client libraries. + PhpSettings php_settings = 23; + + // Settings for Python client libraries. + PythonSettings python_settings = 24; + + // Settings for Node client libraries. + NodeSettings node_settings = 25; + + // Settings for .NET client libraries. + DotnetSettings dotnet_settings = 26; + + // Settings for Ruby client libraries. + RubySettings ruby_settings = 27; + + // Settings for Go client libraries. + GoSettings go_settings = 28; +} + +// This message configures the settings for publishing [Google Cloud Client +// libraries](https://cloud.google.com/apis/docs/cloud-client-libraries) +// generated from the service config. +message Publishing { + // A list of API method settings, e.g. the behavior for methods that use the + // long-running operation pattern. + repeated MethodSettings method_settings = 2; + + // Link to a *public* URI where users can report issues. Example: + // https://issuetracker.google.com/issues/new?component=190865&template=1161103 + string new_issue_uri = 101; + + // Link to product home page. Example: + // https://cloud.google.com/asset-inventory/docs/overview + string documentation_uri = 102; + + // Used as a tracking tag when collecting data about the APIs developer + // relations artifacts like docs, packages delivered to package managers, + // etc. Example: "speech". + string api_short_name = 103; + + // GitHub label to apply to issues and pull requests opened for this API. + string github_label = 104; + + // GitHub teams to be added to CODEOWNERS in the directory in GitHub + // containing source code for the client libraries for this API. + repeated string codeowner_github_teams = 105; + + // A prefix used in sample code when demarking regions to be included in + // documentation. + string doc_tag_prefix = 106; + + // For whom the client library is being published. + ClientLibraryOrganization organization = 107; + + // Client library settings. If the same version string appears multiple + // times in this list, then the last one wins. Settings from earlier + // settings with the same version string are discarded. + repeated ClientLibrarySettings library_settings = 109; + + // Optional link to proto reference documentation. Example: + // https://cloud.google.com/pubsub/lite/docs/reference/rpc + string proto_reference_documentation_uri = 110; +} + +// Settings for Java client libraries. +message JavaSettings { + // The package name to use in Java. Clobbers the java_package option + // set in the protobuf. This should be used **only** by APIs + // who have already set the language_settings.java.package_name" field + // in gapic.yaml. API teams should use the protobuf java_package option + // where possible. + // + // Example of a YAML configuration:: + // + // publishing: + // java_settings: + // library_package: com.google.cloud.pubsub.v1 + string library_package = 1; + + // Configure the Java class name to use instead of the service's for its + // corresponding generated GAPIC client. Keys are fully-qualified + // service names as they appear in the protobuf (including the full + // the language_settings.java.interface_names" field in gapic.yaml. API + // teams should otherwise use the service name as it appears in the + // protobuf. + // + // Example of a YAML configuration:: + // + // publishing: + // java_settings: + // service_class_names: + // - google.pubsub.v1.Publisher: TopicAdmin + // - google.pubsub.v1.Subscriber: SubscriptionAdmin + map service_class_names = 2; + + // Some settings. + CommonLanguageSettings common = 3; +} + +// Settings for C++ client libraries. +message CppSettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Php client libraries. +message PhpSettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Python client libraries. +message PythonSettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Node client libraries. +message NodeSettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Dotnet client libraries. +message DotnetSettings { + // Some settings. + CommonLanguageSettings common = 1; + + // Map from original service names to renamed versions. + // This is used when the default generated types + // would cause a naming conflict. (Neither name is + // fully-qualified.) + // Example: Subscriber to SubscriberServiceApi. + map renamed_services = 2; + + // Map from full resource types to the effective short name + // for the resource. This is used when otherwise resource + // named from different services would cause naming collisions. + // Example entry: + // "datalabeling.googleapis.com/Dataset": "DataLabelingDataset" + map renamed_resources = 3; + + // List of full resource types to ignore during generation. + // This is typically used for API-specific Location resources, + // which should be handled by the generator as if they were actually + // the common Location resources. + // Example entry: "documentai.googleapis.com/Location" + repeated string ignored_resources = 4; + + // Namespaces which must be aliased in snippets due to + // a known (but non-generator-predictable) naming collision + repeated string forced_namespace_aliases = 5; + + // Method signatures (in the form "service.method(signature)") + // which are provided separately, so shouldn't be generated. + // Snippets *calling* these methods are still generated, however. + repeated string handwritten_signatures = 6; +} + +// Settings for Ruby client libraries. +message RubySettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Settings for Go client libraries. +message GoSettings { + // Some settings. + CommonLanguageSettings common = 1; +} + +// Describes the generator configuration for a method. +message MethodSettings { + // Describes settings to use when generating API methods that use the + // long-running operation pattern. + // All default values below are from those used in the client library + // generators (e.g. + // [Java](https://github.com/googleapis/gapic-generator-java/blob/04c2faa191a9b5a10b92392fe8482279c4404803/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java)). + message LongRunning { + // Initial delay after which the first poll request will be made. + // Default value: 5 seconds. + google.protobuf.Duration initial_poll_delay = 1; + + // Multiplier to gradually increase delay between subsequent polls until it + // reaches max_poll_delay. + // Default value: 1.5. + float poll_delay_multiplier = 2; + + // Maximum time between two subsequent poll requests. + // Default value: 45 seconds. + google.protobuf.Duration max_poll_delay = 3; + + // Total polling timeout. + // Default value: 5 minutes. + google.protobuf.Duration total_poll_timeout = 4; + } + + // The fully qualified name of the method, for which the options below apply. + // This is used to find the method to apply the options. + string selector = 1; + + // Describes settings to use for long-running operations when generating + // API methods for RPCs. Complements RPCs that use the annotations in + // google/longrunning/operations.proto. + // + // Example of a YAML configuration:: + // + // publishing: + // method_settings: + // - selector: google.cloud.speech.v2.Speech.BatchRecognize + // long_running: + // initial_poll_delay: + // seconds: 60 # 1 minute + // poll_delay_multiplier: 1.5 + // max_poll_delay: + // seconds: 360 # 6 minutes + // total_poll_timeout: + // seconds: 54000 # 90 minutes + LongRunning long_running = 2; +} + +// The organization for which the client libraries are being published. +// Affects the url where generated docs are published, etc. +enum ClientLibraryOrganization { + // Not useful. + CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED = 0; + + // Google Cloud Platform Org. + CLOUD = 1; + + // Ads (Advertising) Org. + ADS = 2; + + // Photos Org. + PHOTOS = 3; + + // Street View Org. + STREET_VIEW = 4; + + // Shopping Org. + SHOPPING = 5; + + // Geo Org. + GEO = 6; + + // Generative AI - https://developers.generativeai.google + GENERATIVE_AI = 7; +} + +// To where should client libraries be published? +enum ClientLibraryDestination { + // Client libraries will neither be generated nor published to package + // managers. + CLIENT_LIBRARY_DESTINATION_UNSPECIFIED = 0; + + // Generate the client library in a repo under github.com/googleapis, + // but don't publish it to package managers. + GITHUB = 10; + + // Publish the library to package managers like nuget.org and npmjs.com. + PACKAGE_MANAGER = 20; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/config_change.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/config_change.proto new file mode 100644 index 00000000..1dc8044b --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/config_change.proto @@ -0,0 +1,84 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/configchange;configchange"; +option java_multiple_files = true; +option java_outer_classname = "ConfigChangeProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Output generated from semantically comparing two versions of a service +// configuration. +// +// Includes detailed information about a field that have changed with +// applicable advice about potential consequences for the change, such as +// backwards-incompatibility. +message ConfigChange { + // Object hierarchy path to the change, with levels separated by a '.' + // character. For repeated fields, an applicable unique identifier field is + // used for the index (usually selector, name, or id). For maps, the term + // 'key' is used. If the field has no unique identifier, the numeric index + // is used. + // Examples: + // - visibility.rules[selector=="google.LibraryService.ListBooks"].restriction + // - quota.metric_rules[selector=="google"].metric_costs[key=="reads"].value + // - logging.producer_destinations[0] + string element = 1; + + // Value of the changed object in the old Service configuration, + // in JSON format. This field will not be populated if ChangeType == ADDED. + string old_value = 2; + + // Value of the changed object in the new Service configuration, + // in JSON format. This field will not be populated if ChangeType == REMOVED. + string new_value = 3; + + // The type for this change, either ADDED, REMOVED, or MODIFIED. + ChangeType change_type = 4; + + // Collection of advice provided for this change, useful for determining the + // possible impact of this change. + repeated Advice advices = 5; +} + +// Generated advice about this change, used for providing more +// information about how a change will affect the existing service. +message Advice { + // Useful description for why this advice was applied and what actions should + // be taken to mitigate any implied risks. + string description = 2; +} + +// Classifies set of possible modifications to an object in the service +// configuration. +enum ChangeType { + // No value was provided. + CHANGE_TYPE_UNSPECIFIED = 0; + + // The changed object exists in the 'new' service configuration, but not + // in the 'old' service configuration. + ADDED = 1; + + // The changed object exists in the 'old' service configuration, but not + // in the 'new' service configuration. + REMOVED = 2; + + // The changed object exists in both service configurations, but its value + // is different. + MODIFIED = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/consumer.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/consumer.proto new file mode 100644 index 00000000..b7e5df1c --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/consumer.proto @@ -0,0 +1,82 @@ +// Copyright 2016 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "ConsumerProto"; +option java_package = "com.google.api"; + +// A descriptor for defining project properties for a service. One service may +// have many consumer projects, and the service may want to behave differently +// depending on some properties on the project. For example, a project may be +// associated with a school, or a business, or a government agency, a business +// type property on the project may affect how a service responds to the client. +// This descriptor defines which properties are allowed to be set on a project. +// +// Example: +// +// project_properties: +// properties: +// - name: NO_WATERMARK +// type: BOOL +// description: Allows usage of the API without watermarks. +// - name: EXTENDED_TILE_CACHE_PERIOD +// type: INT64 +message ProjectProperties { + // List of per consumer project-specific properties. + repeated Property properties = 1; +} + +// Defines project properties. +// +// API services can define properties that can be assigned to consumer projects +// so that backends can perform response customization without having to make +// additional calls or maintain additional storage. For example, Maps API +// defines properties that controls map tile cache period, or whether to embed a +// watermark in a result. +// +// These values can be set via API producer console. Only API providers can +// define and set these properties. +message Property { + // Supported data type of the property values + enum PropertyType { + // The type is unspecified, and will result in an error. + UNSPECIFIED = 0; + + // The type is `int64`. + INT64 = 1; + + // The type is `bool`. + BOOL = 2; + + // The type is `string`. + STRING = 3; + + // The type is 'double'. + DOUBLE = 4; + } + + // The name of the property (a.k.a key). + string name = 1; + + // The type of this property. + PropertyType type = 2; + + // The description of the property + string description = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/context.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/context.proto new file mode 100644 index 00000000..1b165178 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/context.proto @@ -0,0 +1,90 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "ContextProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Context` defines which contexts an API requests. +// +// Example: +// +// context: +// rules: +// - selector: "*" +// requested: +// - google.rpc.context.ProjectContext +// - google.rpc.context.OriginContext +// +// The above specifies that all methods in the API request +// `google.rpc.context.ProjectContext` and +// `google.rpc.context.OriginContext`. +// +// Available context types are defined in package +// `google.rpc.context`. +// +// This also provides mechanism to allowlist any protobuf message extension that +// can be sent in grpc metadata using “x-goog-ext--bin” and +// “x-goog-ext--jspb” format. For example, list any service +// specific protobuf types that can appear in grpc metadata as follows in your +// yaml file: +// +// Example: +// +// context: +// rules: +// - selector: "google.example.library.v1.LibraryService.CreateBook" +// allowed_request_extensions: +// - google.foo.v1.NewExtension +// allowed_response_extensions: +// - google.foo.v1.NewExtension +// +// You can also specify extension ID instead of fully qualified extension name +// here. +message Context { + // A list of RPC context rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated ContextRule rules = 1; +} + +// A context rule provides information about the context for an individual API +// element. +message ContextRule { + // Selects the methods to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // A list of full type names of requested contexts. + repeated string requested = 2; + + // A list of full type names of provided contexts. + repeated string provided = 3; + + // A list of full type names or extension IDs of extensions allowed in grpc + // side channel from client to backend. + repeated string allowed_request_extensions = 4; + + // A list of full type names or extension IDs of extensions allowed in grpc + // side channel from backend to client. + repeated string allowed_response_extensions = 5; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/control.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/control.proto new file mode 100644 index 00000000..cbbce6f6 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/control.proto @@ -0,0 +1,41 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/policy.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "ControlProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Selects and configures the service controller used by the service. +// +// Example: +// +// control: +// environment: servicecontrol.googleapis.com +message Control { + // The service controller environment to use. If empty, no control plane + // feature (like quota and billing) will be enabled. The recommended value for + // most services is servicecontrol.googleapis.com + string environment = 1; + + // Defines policies applying to the API methods of the service. + repeated MethodPolicy method_policies = 4; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/distribution.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/distribution.proto new file mode 100644 index 00000000..b0bc4930 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/distribution.proto @@ -0,0 +1,213 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/distribution;distribution"; +option java_multiple_files = true; +option java_outer_classname = "DistributionProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Distribution` contains summary statistics for a population of values. It +// optionally contains a histogram representing the distribution of those values +// across a set of buckets. +// +// The summary statistics are the count, mean, sum of the squared deviation from +// the mean, the minimum, and the maximum of the set of population of values. +// The histogram is based on a sequence of buckets and gives a count of values +// that fall into each bucket. The boundaries of the buckets are given either +// explicitly or by formulas for buckets of fixed or exponentially increasing +// widths. +// +// Although it is not forbidden, it is generally a bad idea to include +// non-finite values (infinities or NaNs) in the population of values, as this +// will render the `mean` and `sum_of_squared_deviation` fields meaningless. +message Distribution { + // The range of the population values. + message Range { + // The minimum of the population values. + double min = 1; + + // The maximum of the population values. + double max = 2; + } + + // `BucketOptions` describes the bucket boundaries used to create a histogram + // for the distribution. The buckets can be in a linear sequence, an + // exponential sequence, or each bucket can be specified explicitly. + // `BucketOptions` does not include the number of values in each bucket. + // + // A bucket has an inclusive lower bound and exclusive upper bound for the + // values that are counted for that bucket. The upper bound of a bucket must + // be strictly greater than the lower bound. The sequence of N buckets for a + // distribution consists of an underflow bucket (number 0), zero or more + // finite buckets (number 1 through N - 2) and an overflow bucket (number N - + // 1). The buckets are contiguous: the lower bound of bucket i (i > 0) is the + // same as the upper bound of bucket i - 1. The buckets span the whole range + // of finite values: lower bound of the underflow bucket is -infinity and the + // upper bound of the overflow bucket is +infinity. The finite buckets are + // so-called because both bounds are finite. + message BucketOptions { + // Specifies a linear sequence of buckets that all have the same width + // (except overflow and underflow). Each bucket represents a constant + // absolute uncertainty on the specific value in the bucket. + // + // There are `num_finite_buckets + 2` (= N) buckets. Bucket `i` has the + // following boundaries: + // + // Upper bound (0 <= i < N-1): offset + (width * i). + // + // Lower bound (1 <= i < N): offset + (width * (i - 1)). + message Linear { + // Must be greater than 0. + int32 num_finite_buckets = 1; + + // Must be greater than 0. + double width = 2; + + // Lower bound of the first bucket. + double offset = 3; + } + + // Specifies an exponential sequence of buckets that have a width that is + // proportional to the value of the lower bound. Each bucket represents a + // constant relative uncertainty on a specific value in the bucket. + // + // There are `num_finite_buckets + 2` (= N) buckets. Bucket `i` has the + // following boundaries: + // + // Upper bound (0 <= i < N-1): scale * (growth_factor ^ i). + // + // Lower bound (1 <= i < N): scale * (growth_factor ^ (i - 1)). + message Exponential { + // Must be greater than 0. + int32 num_finite_buckets = 1; + + // Must be greater than 1. + double growth_factor = 2; + + // Must be greater than 0. + double scale = 3; + } + + // Specifies a set of buckets with arbitrary widths. + // + // There are `size(bounds) + 1` (= N) buckets. Bucket `i` has the following + // boundaries: + // + // Upper bound (0 <= i < N-1): bounds[i] + // Lower bound (1 <= i < N); bounds[i - 1] + // + // The `bounds` field must contain at least one element. If `bounds` has + // only one element, then there are no finite buckets, and that single + // element is the common boundary of the overflow and underflow buckets. + message Explicit { + // The values must be monotonically increasing. + repeated double bounds = 1; + } + + // Exactly one of these three fields must be set. + oneof options { + // The linear bucket. + Linear linear_buckets = 1; + + // The exponential buckets. + Exponential exponential_buckets = 2; + + // The explicit buckets. + Explicit explicit_buckets = 3; + } + } + + // Exemplars are example points that may be used to annotate aggregated + // distribution values. They are metadata that gives information about a + // particular value added to a Distribution bucket, such as a trace ID that + // was active when a value was added. They may contain further information, + // such as a example values and timestamps, origin, etc. + message Exemplar { + // Value of the exemplar point. This value determines to which bucket the + // exemplar belongs. + double value = 1; + + // The observation (sampling) time of the above value. + google.protobuf.Timestamp timestamp = 2; + + // Contextual information about the example value. Examples are: + // + // Trace: type.googleapis.com/google.monitoring.v3.SpanContext + // + // Literal string: type.googleapis.com/google.protobuf.StringValue + // + // Labels dropped during aggregation: + // type.googleapis.com/google.monitoring.v3.DroppedLabels + // + // There may be only a single attachment of any given message type in a + // single exemplar, and this is enforced by the system. + repeated google.protobuf.Any attachments = 3; + } + + // The number of values in the population. Must be non-negative. This value + // must equal the sum of the values in `bucket_counts` if a histogram is + // provided. + int64 count = 1; + + // The arithmetic mean of the values in the population. If `count` is zero + // then this field must be zero. + double mean = 2; + + // The sum of squared deviations from the mean of the values in the + // population. For values x_i this is: + // + // Sum[i=1..n]((x_i - mean)^2) + // + // Knuth, "The Art of Computer Programming", Vol. 2, page 232, 3rd edition + // describes Welford's method for accumulating this sum in one pass. + // + // If `count` is zero then this field must be zero. + double sum_of_squared_deviation = 3; + + // If specified, contains the range of the population values. The field + // must not be present if the `count` is zero. + Range range = 4; + + // Defines the histogram bucket boundaries. If the distribution does not + // contain a histogram, then omit this field. + BucketOptions bucket_options = 6; + + // The number of values in each bucket of the histogram, as described in + // `bucket_options`. If the distribution does not have a histogram, then omit + // this field. If there is a histogram, then the sum of the values in + // `bucket_counts` must equal the value in the `count` field of the + // distribution. + // + // If present, `bucket_counts` should contain N values, where N is the number + // of buckets specified in `bucket_options`. If you supply fewer than N + // values, the remaining values are assumed to be 0. + // + // The order of the values in `bucket_counts` follows the bucket numbering + // schemes described for the three bucket types. The first value must be the + // count for the underflow bucket (number 0). The next N-2 values are the + // counts for the finite buckets (number 1 through N-2). The N'th value in + // `bucket_counts` is the count for the overflow bucket (number N-1). + repeated int64 bucket_counts = 7; + + // Must be in increasing order of `value` field. + repeated Exemplar exemplars = 10; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/documentation.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/documentation.proto new file mode 100644 index 00000000..0dabdfcf --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/documentation.proto @@ -0,0 +1,168 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "DocumentationProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Documentation` provides the information for describing a service. +// +// Example: +//
    documentation:
    +//   summary: >
    +//     The Google Calendar API gives access
    +//     to most calendar features.
    +//   pages:
    +//   - name: Overview
    +//     content: (== include google/foo/overview.md ==)
    +//   - name: Tutorial
    +//     content: (== include google/foo/tutorial.md ==)
    +//     subpages;
    +//     - name: Java
    +//       content: (== include google/foo/tutorial_java.md ==)
    +//   rules:
    +//   - selector: google.calendar.Calendar.Get
    +//     description: >
    +//       ...
    +//   - selector: google.calendar.Calendar.Put
    +//     description: >
    +//       ...
    +// 
    +// Documentation is provided in markdown syntax. In addition to +// standard markdown features, definition lists, tables and fenced +// code blocks are supported. Section headers can be provided and are +// interpreted relative to the section nesting of the context where +// a documentation fragment is embedded. +// +// Documentation from the IDL is merged with documentation defined +// via the config at normalization time, where documentation provided +// by config rules overrides IDL provided. +// +// A number of constructs specific to the API platform are supported +// in documentation text. +// +// In order to reference a proto element, the following +// notation can be used: +//
    [fully.qualified.proto.name][]
    +// To override the display text used for the link, this can be used: +//
    [display text][fully.qualified.proto.name]
    +// Text can be excluded from doc using the following notation: +//
    (-- internal comment --)
    +// +// A few directives are available in documentation. Note that +// directives must appear on a single line to be properly +// identified. The `include` directive includes a markdown file from +// an external source: +//
    (== include path/to/file ==)
    +// The `resource_for` directive marks a message to be the resource of +// a collection in REST view. If it is not specified, tools attempt +// to infer the resource from the operations in a collection: +//
    (== resource_for v1.shelves.books ==)
    +// The directive `suppress_warning` does not directly affect documentation +// and is documented together with service config validation. +message Documentation { + // A short description of what the service does. The summary must be plain + // text. It becomes the overview of the service displayed in Google Cloud + // Console. + // NOTE: This field is equivalent to the standard field `description`. + string summary = 1; + + // The top level pages for the documentation set. + repeated Page pages = 5; + + // A list of documentation rules that apply to individual API elements. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated DocumentationRule rules = 3; + + // The URL to the root of documentation. + string documentation_root_url = 4; + + // Specifies the service root url if the default one (the service name + // from the yaml file) is not suitable. This can be seen in any fully + // specified service urls as well as sections that show a base that other + // urls are relative to. + string service_root_url = 6; + + // Declares a single overview page. For example: + //
    documentation:
    +  //   summary: ...
    +  //   overview: (== include overview.md ==)
    +  // 
    + // This is a shortcut for the following declaration (using pages style): + //
    documentation:
    +  //   summary: ...
    +  //   pages:
    +  //   - name: Overview
    +  //     content: (== include overview.md ==)
    +  // 
    + // Note: you cannot specify both `overview` field and `pages` field. + string overview = 2; +} + +// A documentation rule provides information about individual API elements. +message DocumentationRule { + // The selector is a comma-separated list of patterns for any element such as + // a method, a field, an enum value. Each pattern is a qualified name of the + // element which may end in "*", indicating a wildcard. Wildcards are only + // allowed at the end and for a whole component of the qualified name, + // i.e. "foo.*" is ok, but not "foo.b*" or "foo.*.bar". A wildcard will match + // one or more components. To specify a default for all applicable elements, + // the whole pattern "*" is used. + string selector = 1; + + // Description of the selected proto element (e.g. a message, a method, a + // 'service' definition, or a field). Defaults to leading & trailing comments + // taken from the proto source definition of the proto element. + string description = 2; + + // Deprecation description of the selected element(s). It can be provided if + // an element is marked as `deprecated`. + string deprecation_description = 3; +} + +// Represents a documentation page. A page can contain subpages to represent +// nested documentation set structure. +message Page { + // The name of the page. It will be used as an identity of the page to + // generate URI of the page, text of the link to this page in navigation, + // etc. The full page name (start from the root page name to this page + // concatenated with `.`) can be used as reference to the page in your + // documentation. For example: + //
    pages:
    +  // - name: Tutorial
    +  //   content: (== include tutorial.md ==)
    +  //   subpages:
    +  //   - name: Java
    +  //     content: (== include tutorial_java.md ==)
    +  // 
    + // You can reference `Java` page using Markdown reference link syntax: + // `[Java][Tutorial.Java]`. + string name = 1; + + // The Markdown content of the page. You can use (== include {path} + // ==) to include content from a Markdown file. The content can be + // used to produce the documentation page such as HTML format page. + string content = 2; + + // Subpages of this page. The order of subpages specified here will be + // honored in the generated docset. + repeated Page subpages = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/endpoint.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/endpoint.proto new file mode 100644 index 00000000..7f6dca7c --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/endpoint.proto @@ -0,0 +1,73 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "EndpointProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Endpoint` describes a network address of a service that serves a set of +// APIs. It is commonly known as a service endpoint. A service may expose +// any number of service endpoints, and all service endpoints share the same +// service definition, such as quota limits and monitoring metrics. +// +// Example: +// +// type: google.api.Service +// name: library-example.googleapis.com +// endpoints: +// # Declares network address `https://library-example.googleapis.com` +// # for service `library-example.googleapis.com`. The `https` scheme +// # is implicit for all service endpoints. Other schemes may be +// # supported in the future. +// - name: library-example.googleapis.com +// allow_cors: false +// - name: content-staging-library-example.googleapis.com +// # Allows HTTP OPTIONS calls to be passed to the API frontend, for it +// # to decide whether the subsequent cross-origin request is allowed +// # to proceed. +// allow_cors: true +message Endpoint { + // The canonical name of this endpoint. + string name = 1; + + // Unimplemented. Dot not use. + // + // DEPRECATED: This field is no longer supported. Instead of using aliases, + // please specify multiple [google.api.Endpoint][google.api.Endpoint] for each + // of the intended aliases. + // + // Additional names that this endpoint will be hosted on. + repeated string aliases = 2 [deprecated = true]; + + // The specification of an Internet routable address of API frontend that will + // handle requests to this [API + // Endpoint](https://cloud.google.com/apis/design/glossary). It should be + // either a valid IPv4 address or a fully-qualified domain name. For example, + // "8.8.8.8" or "myservice.appspot.com". + string target = 101; + + // Allowing + // [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing), aka + // cross-domain traffic, would allow the backends served from this endpoint to + // receive and respond to HTTP OPTIONS requests. The response will be used by + // the browser to determine whether the subsequent cross-origin request is + // allowed to proceed. + bool allow_cors = 5; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/error_reason.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/error_reason.proto new file mode 100644 index 00000000..c0509be4 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/error_reason.proto @@ -0,0 +1,570 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/error_reason;error_reason"; +option java_multiple_files = true; +option java_outer_classname = "ErrorReasonProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the supported values for `google.rpc.ErrorInfo.reason` for the +// `googleapis.com` error domain. This error domain is reserved for [Service +// Infrastructure](https://cloud.google.com/service-infrastructure/docs/overview). +// For each error info of this domain, the metadata key "service" refers to the +// logical identifier of an API service, such as "pubsub.googleapis.com". The +// "consumer" refers to the entity that consumes an API Service. It typically is +// a Google project that owns the client application or the server resource, +// such as "projects/123". Other metadata keys are specific to each error +// reason. For more information, see the definition of the specific error +// reason. +enum ErrorReason { + // Do not use this default value. + ERROR_REASON_UNSPECIFIED = 0; + + // The request is calling a disabled service for a consumer. + // + // Example of an ErrorInfo when the consumer "projects/123" contacting + // "pubsub.googleapis.com" service which is disabled: + // + // { "reason": "SERVICE_DISABLED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "pubsub.googleapis.com" + // } + // } + // + // This response indicates the "pubsub.googleapis.com" has been disabled in + // "projects/123". + SERVICE_DISABLED = 1; + + // The request whose associated billing account is disabled. + // + // Example of an ErrorInfo when the consumer "projects/123" fails to contact + // "pubsub.googleapis.com" service because the associated billing account is + // disabled: + // + // { "reason": "BILLING_DISABLED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "pubsub.googleapis.com" + // } + // } + // + // This response indicates the billing account associated has been disabled. + BILLING_DISABLED = 2; + + // The request is denied because the provided [API + // key](https://cloud.google.com/docs/authentication/api-keys) is invalid. It + // may be in a bad format, cannot be found, or has been expired). + // + // Example of an ErrorInfo when the request is contacting + // "storage.googleapis.com" service with an invalid API key: + // + // { "reason": "API_KEY_INVALID", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // } + // } + API_KEY_INVALID = 3; + + // The request is denied because it violates [API key API + // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_api_restrictions). + // + // Example of an ErrorInfo when the consumer "projects/123" fails to call the + // "storage.googleapis.com" service because this service is restricted in the + // API key: + // + // { "reason": "API_KEY_SERVICE_BLOCKED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com" + // } + // } + API_KEY_SERVICE_BLOCKED = 4; + + // The request is denied because it violates [API key HTTP + // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_http_restrictions). + // + // Example of an ErrorInfo when the consumer "projects/123" fails to call + // "storage.googleapis.com" service because the http referrer of the request + // violates API key HTTP restrictions: + // + // { "reason": "API_KEY_HTTP_REFERRER_BLOCKED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com", + // } + // } + API_KEY_HTTP_REFERRER_BLOCKED = 7; + + // The request is denied because it violates [API key IP address + // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions). + // + // Example of an ErrorInfo when the consumer "projects/123" fails to call + // "storage.googleapis.com" service because the caller IP of the request + // violates API key IP address restrictions: + // + // { "reason": "API_KEY_IP_ADDRESS_BLOCKED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com", + // } + // } + API_KEY_IP_ADDRESS_BLOCKED = 8; + + // The request is denied because it violates [API key Android application + // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions). + // + // Example of an ErrorInfo when the consumer "projects/123" fails to call + // "storage.googleapis.com" service because the request from the Android apps + // violates the API key Android application restrictions: + // + // { "reason": "API_KEY_ANDROID_APP_BLOCKED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com" + // } + // } + API_KEY_ANDROID_APP_BLOCKED = 9; + + // The request is denied because it violates [API key iOS application + // restrictions](https://cloud.google.com/docs/authentication/api-keys#adding_application_restrictions). + // + // Example of an ErrorInfo when the consumer "projects/123" fails to call + // "storage.googleapis.com" service because the request from the iOS apps + // violates the API key iOS application restrictions: + // + // { "reason": "API_KEY_IOS_APP_BLOCKED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com" + // } + // } + API_KEY_IOS_APP_BLOCKED = 13; + + // The request is denied because there is not enough rate quota for the + // consumer. + // + // Example of an ErrorInfo when the consumer "projects/123" fails to contact + // "pubsub.googleapis.com" service because consumer's rate quota usage has + // reached the maximum value set for the quota limit + // "ReadsPerMinutePerProject" on the quota metric + // "pubsub.googleapis.com/read_requests": + // + // { "reason": "RATE_LIMIT_EXCEEDED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "pubsub.googleapis.com", + // "quota_metric": "pubsub.googleapis.com/read_requests", + // "quota_limit": "ReadsPerMinutePerProject" + // } + // } + // + // Example of an ErrorInfo when the consumer "projects/123" checks quota on + // the service "dataflow.googleapis.com" and hits the organization quota + // limit "DefaultRequestsPerMinutePerOrganization" on the metric + // "dataflow.googleapis.com/default_requests". + // + // { "reason": "RATE_LIMIT_EXCEEDED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "dataflow.googleapis.com", + // "quota_metric": "dataflow.googleapis.com/default_requests", + // "quota_limit": "DefaultRequestsPerMinutePerOrganization" + // } + // } + RATE_LIMIT_EXCEEDED = 5; + + // The request is denied because there is not enough resource quota for the + // consumer. + // + // Example of an ErrorInfo when the consumer "projects/123" fails to contact + // "compute.googleapis.com" service because consumer's resource quota usage + // has reached the maximum value set for the quota limit "VMsPerProject" + // on the quota metric "compute.googleapis.com/vms": + // + // { "reason": "RESOURCE_QUOTA_EXCEEDED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "compute.googleapis.com", + // "quota_metric": "compute.googleapis.com/vms", + // "quota_limit": "VMsPerProject" + // } + // } + // + // Example of an ErrorInfo when the consumer "projects/123" checks resource + // quota on the service "dataflow.googleapis.com" and hits the organization + // quota limit "jobs-per-organization" on the metric + // "dataflow.googleapis.com/job_count". + // + // { "reason": "RESOURCE_QUOTA_EXCEEDED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "dataflow.googleapis.com", + // "quota_metric": "dataflow.googleapis.com/job_count", + // "quota_limit": "jobs-per-organization" + // } + // } + RESOURCE_QUOTA_EXCEEDED = 6; + + // The request whose associated billing account address is in a tax restricted + // location, violates the local tax restrictions when creating resources in + // the restricted region. + // + // Example of an ErrorInfo when creating the Cloud Storage Bucket in the + // container "projects/123" under a tax restricted region + // "locations/asia-northeast3": + // + // { "reason": "LOCATION_TAX_POLICY_VIOLATED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com", + // "location": "locations/asia-northeast3" + // } + // } + // + // This response indicates creating the Cloud Storage Bucket in + // "locations/asia-northeast3" violates the location tax restriction. + LOCATION_TAX_POLICY_VIOLATED = 10; + + // The request is denied because the caller does not have required permission + // on the user project "projects/123" or the user project is invalid. For more + // information, check the [userProject System + // Parameters](https://cloud.google.com/apis/docs/system-parameters). + // + // Example of an ErrorInfo when the caller is calling Cloud Storage service + // with insufficient permissions on the user project: + // + // { "reason": "USER_PROJECT_DENIED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com" + // } + // } + USER_PROJECT_DENIED = 11; + + // The request is denied because the consumer "projects/123" is suspended due + // to Terms of Service(Tos) violations. Check [Project suspension + // guidelines](https://cloud.google.com/resource-manager/docs/project-suspension-guidelines) + // for more information. + // + // Example of an ErrorInfo when calling Cloud Storage service with the + // suspended consumer "projects/123": + // + // { "reason": "CONSUMER_SUSPENDED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com" + // } + // } + CONSUMER_SUSPENDED = 12; + + // The request is denied because the associated consumer is invalid. It may be + // in a bad format, cannot be found, or have been deleted. + // + // Example of an ErrorInfo when calling Cloud Storage service with the + // invalid consumer "projects/123": + // + // { "reason": "CONSUMER_INVALID", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "storage.googleapis.com" + // } + // } + CONSUMER_INVALID = 14; + + // The request is denied because it violates [VPC Service + // Controls](https://cloud.google.com/vpc-service-controls/docs/overview). + // The 'uid' field is a random generated identifier that customer can use it + // to search the audit log for a request rejected by VPC Service Controls. For + // more information, please refer [VPC Service Controls + // Troubleshooting](https://cloud.google.com/vpc-service-controls/docs/troubleshooting#unique-id) + // + // Example of an ErrorInfo when the consumer "projects/123" fails to call + // Cloud Storage service because the request is prohibited by the VPC Service + // Controls. + // + // { "reason": "SECURITY_POLICY_VIOLATED", + // "domain": "googleapis.com", + // "metadata": { + // "uid": "123456789abcde", + // "consumer": "projects/123", + // "service": "storage.googleapis.com" + // } + // } + SECURITY_POLICY_VIOLATED = 15; + + // The request is denied because the provided access token has expired. + // + // Example of an ErrorInfo when the request is calling Cloud Storage service + // with an expired access token: + // + // { "reason": "ACCESS_TOKEN_EXPIRED", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // "method": "google.storage.v1.Storage.GetObject" + // } + // } + ACCESS_TOKEN_EXPIRED = 16; + + // The request is denied because the provided access token doesn't have at + // least one of the acceptable scopes required for the API. Please check + // [OAuth 2.0 Scopes for Google + // APIs](https://developers.google.com/identity/protocols/oauth2/scopes) for + // the list of the OAuth 2.0 scopes that you might need to request to access + // the API. + // + // Example of an ErrorInfo when the request is calling Cloud Storage service + // with an access token that is missing required scopes: + // + // { "reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // "method": "google.storage.v1.Storage.GetObject" + // } + // } + ACCESS_TOKEN_SCOPE_INSUFFICIENT = 17; + + // The request is denied because the account associated with the provided + // access token is in an invalid state, such as disabled or deleted. + // For more information, see https://cloud.google.com/docs/authentication. + // + // Warning: For privacy reasons, the server may not be able to disclose the + // email address for some accounts. The client MUST NOT depend on the + // availability of the `email` attribute. + // + // Example of an ErrorInfo when the request is to the Cloud Storage API with + // an access token that is associated with a disabled or deleted [service + // account](http://cloud/iam/docs/service-accounts): + // + // { "reason": "ACCOUNT_STATE_INVALID", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // "method": "google.storage.v1.Storage.GetObject", + // "email": "user@123.iam.gserviceaccount.com" + // } + // } + ACCOUNT_STATE_INVALID = 18; + + // The request is denied because the type of the provided access token is not + // supported by the API being called. + // + // Example of an ErrorInfo when the request is to the Cloud Storage API with + // an unsupported token type. + // + // { "reason": "ACCESS_TOKEN_TYPE_UNSUPPORTED", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // "method": "google.storage.v1.Storage.GetObject" + // } + // } + ACCESS_TOKEN_TYPE_UNSUPPORTED = 19; + + // The request is denied because the request doesn't have any authentication + // credentials. For more information regarding the supported authentication + // strategies for Google Cloud APIs, see + // https://cloud.google.com/docs/authentication. + // + // Example of an ErrorInfo when the request is to the Cloud Storage API + // without any authentication credentials. + // + // { "reason": "CREDENTIALS_MISSING", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // "method": "google.storage.v1.Storage.GetObject" + // } + // } + CREDENTIALS_MISSING = 20; + + // The request is denied because the provided project owning the resource + // which acts as the [API + // consumer](https://cloud.google.com/apis/design/glossary#api_consumer) is + // invalid. It may be in a bad format or empty. + // + // Example of an ErrorInfo when the request is to the Cloud Functions API, + // but the offered resource project in the request in a bad format which can't + // perform the ListFunctions method. + // + // { "reason": "RESOURCE_PROJECT_INVALID", + // "domain": "googleapis.com", + // "metadata": { + // "service": "cloudfunctions.googleapis.com", + // "method": + // "google.cloud.functions.v1.CloudFunctionsService.ListFunctions" + // } + // } + RESOURCE_PROJECT_INVALID = 21; + + // The request is denied because the provided session cookie is missing, + // invalid or failed to decode. + // + // Example of an ErrorInfo when the request is calling Cloud Storage service + // with a SID cookie which can't be decoded. + // + // { "reason": "SESSION_COOKIE_INVALID", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // "method": "google.storage.v1.Storage.GetObject", + // "cookie": "SID" + // } + // } + SESSION_COOKIE_INVALID = 23; + + // The request is denied because the user is from a Google Workspace customer + // that blocks their users from accessing a particular service. + // + // Example scenario: https://support.google.com/a/answer/9197205?hl=en + // + // Example of an ErrorInfo when access to Google Cloud Storage service is + // blocked by the Google Workspace administrator: + // + // { "reason": "USER_BLOCKED_BY_ADMIN", + // "domain": "googleapis.com", + // "metadata": { + // "service": "storage.googleapis.com", + // "method": "google.storage.v1.Storage.GetObject", + // } + // } + USER_BLOCKED_BY_ADMIN = 24; + + // The request is denied because the resource service usage is restricted + // by administrators according to the organization policy constraint. + // For more information see + // https://cloud.google.com/resource-manager/docs/organization-policy/restricting-services. + // + // Example of an ErrorInfo when access to Google Cloud Storage service is + // restricted by Resource Usage Restriction policy: + // + // { "reason": "RESOURCE_USAGE_RESTRICTION_VIOLATED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/project-123", + // "service": "storage.googleapis.com" + // } + // } + RESOURCE_USAGE_RESTRICTION_VIOLATED = 25; + + // Unimplemented. Do not use. + // + // The request is denied because it contains unsupported system parameters in + // URL query parameters or HTTP headers. For more information, + // see https://cloud.google.com/apis/docs/system-parameters + // + // Example of an ErrorInfo when access "pubsub.googleapis.com" service with + // a request header of "x-goog-user-ip": + // + // { "reason": "SYSTEM_PARAMETER_UNSUPPORTED", + // "domain": "googleapis.com", + // "metadata": { + // "service": "pubsub.googleapis.com" + // "parameter": "x-goog-user-ip" + // } + // } + SYSTEM_PARAMETER_UNSUPPORTED = 26; + + // The request is denied because it violates Org Restriction: the requested + // resource does not belong to allowed organizations specified in + // "X-Goog-Allowed-Resources" header. + // + // Example of an ErrorInfo when accessing a GCP resource that is restricted by + // Org Restriction for "pubsub.googleapis.com" service. + // + // { + // reason: "ORG_RESTRICTION_VIOLATION" + // domain: "googleapis.com" + // metadata { + // "consumer":"projects/123456" + // "service": "pubsub.googleapis.com" + // } + // } + ORG_RESTRICTION_VIOLATION = 27; + + // The request is denied because "X-Goog-Allowed-Resources" header is in a bad + // format. + // + // Example of an ErrorInfo when + // accessing "pubsub.googleapis.com" service with an invalid + // "X-Goog-Allowed-Resources" request header. + // + // { + // reason: "ORG_RESTRICTION_HEADER_INVALID" + // domain: "googleapis.com" + // metadata { + // "consumer":"projects/123456" + // "service": "pubsub.googleapis.com" + // } + // } + ORG_RESTRICTION_HEADER_INVALID = 28; + + // Unimplemented. Do not use. + // + // The request is calling a service that is not visible to the consumer. + // + // Example of an ErrorInfo when the consumer "projects/123" contacting + // "pubsub.googleapis.com" service which is not visible to the consumer. + // + // { "reason": "SERVICE_NOT_VISIBLE", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "pubsub.googleapis.com" + // } + // } + // + // This response indicates the "pubsub.googleapis.com" is not visible to + // "projects/123" (or it may not exist). + SERVICE_NOT_VISIBLE = 29; + + // The request is related to a project for which GCP access is suspended. + // + // Example of an ErrorInfo when the consumer "projects/123" fails to contact + // "pubsub.googleapis.com" service because GCP access is suspended: + // + // { "reason": "GCP_SUSPENDED", + // "domain": "googleapis.com", + // "metadata": { + // "consumer": "projects/123", + // "service": "pubsub.googleapis.com" + // } + // } + // + // This response indicates the associated GCP account has been suspended. + GCP_SUSPENDED = 30; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_behavior.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_behavior.proto new file mode 100644 index 00000000..344cb0b1 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_behavior.proto @@ -0,0 +1,104 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "FieldBehaviorProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.FieldOptions { + // A designation of a specific field behavior (required, output only, etc.) + // in protobuf messages. + // + // Examples: + // + // string name = 1 [(google.api.field_behavior) = REQUIRED]; + // State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; + // google.protobuf.Duration ttl = 1 + // [(google.api.field_behavior) = INPUT_ONLY]; + // google.protobuf.Timestamp expire_time = 1 + // [(google.api.field_behavior) = OUTPUT_ONLY, + // (google.api.field_behavior) = IMMUTABLE]; + repeated google.api.FieldBehavior field_behavior = 1052; +} + +// An indicator of the behavior of a given field (for example, that a field +// is required in requests, or given as output but ignored as input). +// This **does not** change the behavior in protocol buffers itself; it only +// denotes the behavior and may affect how API tooling handles the field. +// +// Note: This enum **may** receive new values in the future. +enum FieldBehavior { + // Conventional default for enums. Do not use this. + FIELD_BEHAVIOR_UNSPECIFIED = 0; + + // Specifically denotes a field as optional. + // While all fields in protocol buffers are optional, this may be specified + // for emphasis if appropriate. + OPTIONAL = 1; + + // Denotes a field as required. + // This indicates that the field **must** be provided as part of the request, + // and failure to do so will cause an error (usually `INVALID_ARGUMENT`). + REQUIRED = 2; + + // Denotes a field as output only. + // This indicates that the field is provided in responses, but including the + // field in a request does nothing (the server *must* ignore it and + // *must not* throw an error as a result of the field's presence). + OUTPUT_ONLY = 3; + + // Denotes a field as input only. + // This indicates that the field is provided in requests, and the + // corresponding field is not included in output. + INPUT_ONLY = 4; + + // Denotes a field as immutable. + // This indicates that the field may be set once in a request to create a + // resource, but may not be changed thereafter. + IMMUTABLE = 5; + + // Denotes that a (repeated) field is an unordered list. + // This indicates that the service may provide the elements of the list + // in any arbitrary order, rather than the order the user originally + // provided. Additionally, the list's order may or may not be stable. + UNORDERED_LIST = 6; + + // Denotes that this field returns a non-empty default value if not set. + // This indicates that if the user provides the empty value in a request, + // a non-empty value will be returned. The user will not be aware of what + // non-empty value to expect. + NON_EMPTY_DEFAULT = 7; + + // Denotes that the field in a resource (a message annotated with + // google.api.resource) is used in the resource name to uniquely identify the + // resource. For AIP-compliant APIs, this should only be applied to the + // `name` field on the resource. + // + // This behavior should not be applied to references to other resources within + // the message. + // + // The identifier field of resources often have different field behavior + // depending on the request it is embedded in (e.g. for Create methods name + // is optional and unused, while for Update methods it is required). Instead + // of method-specific annotations, only `IDENTIFIER` is required. + IDENTIFIER = 8; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_info.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_info.proto new file mode 100644 index 00000000..dd66340a --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/field_info.proto @@ -0,0 +1,79 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "FieldInfoProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.FieldOptions { + // Rich semantic descriptor of an API field beyond the basic typing. + // + // Examples: + // + // string request_id = 1 [(google.api.field_info).format = UUID4]; + // string old_ip_address = 2 [(google.api.field_info).format = IPV4]; + // string new_ip_address = 3 [(google.api.field_info).format = IPV6]; + // string actual_ip_address = 4 [ + // (google.api.field_info).format = IPV4_OR_IPV6 + // ]; + google.api.FieldInfo field_info = 291403980; +} + +// Rich semantic information of an API field beyond basic typing. +message FieldInfo { + // The standard format of a field value. The supported formats are all backed + // by either an RFC defined by the IETF or a Google-defined AIP. + enum Format { + // Default, unspecified value. + FORMAT_UNSPECIFIED = 0; + + // Universally Unique Identifier, version 4, value as defined by + // https://datatracker.ietf.org/doc/html/rfc4122. The value may be + // normalized to entirely lowercase letters. For example, the value + // `F47AC10B-58CC-0372-8567-0E02B2C3D479` would be normalized to + // `f47ac10b-58cc-0372-8567-0e02b2c3d479`. + UUID4 = 1; + + // Internet Protocol v4 value as defined by [RFC + // 791](https://datatracker.ietf.org/doc/html/rfc791). The value may be + // condensed, with leading zeros in each octet stripped. For example, + // `001.022.233.040` would be condensed to `1.22.233.40`. + IPV4 = 2; + + // Internet Protocol v6 value as defined by [RFC + // 2460](https://datatracker.ietf.org/doc/html/rfc2460). The value may be + // normalized to entirely lowercase letters, and zero-padded partial and + // empty octets. For example, the value `2001:DB8::` would be normalized to + // `2001:0db8:0:0`. + IPV6 = 3; + + // An IP address in either v4 or v6 format as described by the individual + // values defined herein. See the comments on the IPV4 and IPV6 types for + // allowed normalizations of each. + IPV4_OR_IPV6 = 4; + } + + // The standard format of a field value. This does not explicitly configure + // any API consumer, just documents the API's format for the field it is + // applied to. + Format format = 1; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/http.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/http.proto new file mode 100644 index 00000000..31d867a2 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/http.proto @@ -0,0 +1,379 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// # gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +// "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +// "123456")` +// +// ## Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They +// are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL +// query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP +// request body, all +// fields are passed via URL path and URL query parameters. +// +// ### Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// ## Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// Example: +// +// http: +// rules: +// # Selects a gRPC method and applies HttpRule to it. +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// ## Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/httpbody.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/httpbody.proto new file mode 100644 index 00000000..7f1685e8 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/httpbody.proto @@ -0,0 +1,81 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/any.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/httpbody;httpbody"; +option java_multiple_files = true; +option java_outer_classname = "HttpBodyProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Message that represents an arbitrary HTTP body. It should only be used for +// payload formats that can't be represented as JSON, such as raw binary or +// an HTML page. +// +// +// This message can be used both in streaming and non-streaming API methods in +// the request as well as the response. +// +// It can be used as a top-level request field, which is convenient if one +// wants to extract parameters from either the URL or HTTP template into the +// request fields and also want access to the raw HTTP body. +// +// Example: +// +// message GetResourceRequest { +// // A unique request id. +// string request_id = 1; +// +// // The raw HTTP body is bound to this field. +// google.api.HttpBody http_body = 2; +// +// } +// +// service ResourceService { +// rpc GetResource(GetResourceRequest) +// returns (google.api.HttpBody); +// rpc UpdateResource(google.api.HttpBody) +// returns (google.protobuf.Empty); +// +// } +// +// Example with streaming methods: +// +// service CaldavService { +// rpc GetCalendar(stream google.api.HttpBody) +// returns (stream google.api.HttpBody); +// rpc UpdateCalendar(stream google.api.HttpBody) +// returns (stream google.api.HttpBody); +// +// } +// +// Use of this type only changes how the request and response bodies are +// handled, all other features will continue to work unchanged. +message HttpBody { + // The HTTP Content-Type header value specifying the content type of the body. + string content_type = 1; + + // The HTTP request/response body as raw binary. + bytes data = 2; + + // Application specific response metadata. Must be set in the first response + // for streaming APIs. + repeated google.protobuf.Any extensions = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/label.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/label.proto new file mode 100644 index 00000000..698f6bd4 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/label.proto @@ -0,0 +1,48 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/label;label"; +option java_multiple_files = true; +option java_outer_classname = "LabelProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// A description of a label. +message LabelDescriptor { + // Value types that can be used as label values. + enum ValueType { + // A variable-length string. This is the default. + STRING = 0; + + // Boolean; true or false. + BOOL = 1; + + // A 64-bit signed integer. + INT64 = 2; + } + + // The label key. + string key = 1; + + // The type of data that can be assigned to the label. + ValueType value_type = 2; + + // A human-readable description for the label. + string description = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/launch_stage.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/launch_stage.proto new file mode 100644 index 00000000..9802de79 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/launch_stage.proto @@ -0,0 +1,72 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api;api"; +option java_multiple_files = true; +option java_outer_classname = "LaunchStageProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// The launch stage as defined by [Google Cloud Platform +// Launch Stages](https://cloud.google.com/terms/launch-stages). +enum LaunchStage { + // Do not use this default value. + LAUNCH_STAGE_UNSPECIFIED = 0; + + // The feature is not yet implemented. Users can not use it. + UNIMPLEMENTED = 6; + + // Prelaunch features are hidden from users and are only visible internally. + PRELAUNCH = 7; + + // Early Access features are limited to a closed group of testers. To use + // these features, you must sign up in advance and sign a Trusted Tester + // agreement (which includes confidentiality provisions). These features may + // be unstable, changed in backward-incompatible ways, and are not + // guaranteed to be released. + EARLY_ACCESS = 1; + + // Alpha is a limited availability test for releases before they are cleared + // for widespread use. By Alpha, all significant design issues are resolved + // and we are in the process of verifying functionality. Alpha customers + // need to apply for access, agree to applicable terms, and have their + // projects allowlisted. Alpha releases don't have to be feature complete, + // no SLAs are provided, and there are no technical support obligations, but + // they will be far enough along that customers can actually use them in + // test environments or for limited-use tests -- just like they would in + // normal production cases. + ALPHA = 2; + + // Beta is the point at which we are ready to open a release for any + // customer to use. There are no SLA or technical support obligations in a + // Beta release. Products will be complete from a feature perspective, but + // may have some open outstanding issues. Beta releases are suitable for + // limited production use cases. + BETA = 3; + + // GA features are open to all developers and are considered stable and + // fully qualified for production use. + GA = 4; + + // Deprecated features are scheduled to be shut down and removed. For more + // information, see the "Deprecation Policy" section of our [Terms of + // Service](https://cloud.google.com/terms/) + // and the [Google Cloud Platform Subject to the Deprecation + // Policy](https://cloud.google.com/terms/deprecation) documentation. + DEPRECATED = 5; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/log.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/log.proto new file mode 100644 index 00000000..416c4f6c --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/log.proto @@ -0,0 +1,54 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/label.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "LogProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// A description of a log type. Example in YAML format: +// +// - name: library.googleapis.com/activity_history +// description: The history of borrowing and returning library items. +// display_name: Activity +// labels: +// - key: /customer_id +// description: Identifier of a library customer +message LogDescriptor { + // The name of the log. It must be less than 512 characters long and can + // include the following characters: upper- and lower-case alphanumeric + // characters [A-Za-z0-9], and punctuation characters including + // slash, underscore, hyphen, period [/_-.]. + string name = 1; + + // The set of labels that are available to describe a specific log entry. + // Runtime requests that contain labels not specified here are + // considered invalid. + repeated LabelDescriptor labels = 2; + + // A human-readable description of this log. This information appears in + // the documentation and can contain details. + string description = 3; + + // The human-readable name for this log. This information appears on + // the user interface and should be concise. + string display_name = 4; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/logging.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/logging.proto new file mode 100644 index 00000000..650786fd --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/logging.proto @@ -0,0 +1,81 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "LoggingProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Logging configuration of the service. +// +// The following example shows how to configure logs to be sent to the +// producer and consumer projects. In the example, the `activity_history` +// log is sent to both the producer and consumer projects, whereas the +// `purchase_history` log is only sent to the producer project. +// +// monitored_resources: +// - type: library.googleapis.com/branch +// labels: +// - key: /city +// description: The city where the library branch is located in. +// - key: /name +// description: The name of the branch. +// logs: +// - name: activity_history +// labels: +// - key: /customer_id +// - name: purchase_history +// logging: +// producer_destinations: +// - monitored_resource: library.googleapis.com/branch +// logs: +// - activity_history +// - purchase_history +// consumer_destinations: +// - monitored_resource: library.googleapis.com/branch +// logs: +// - activity_history +message Logging { + // Configuration of a specific logging destination (the producer project + // or the consumer project). + message LoggingDestination { + // The monitored resource type. The type must be defined in the + // [Service.monitored_resources][google.api.Service.monitored_resources] + // section. + string monitored_resource = 3; + + // Names of the logs to be sent to this destination. Each name must + // be defined in the [Service.logs][google.api.Service.logs] section. If the + // log name is not a domain scoped name, it will be automatically prefixed + // with the service name followed by "/". + repeated string logs = 1; + } + + // Logging configurations for sending logs to the producer project. + // There can be multiple producer destinations, each one must have a + // different monitored resource type. A log can be used in at most + // one producer destination. + repeated LoggingDestination producer_destinations = 1; + + // Logging configurations for sending logs to the consumer project. + // There can be multiple consumer destinations, each one must have a + // different monitored resource type. A log can be used in at most + // one consumer destination. + repeated LoggingDestination consumer_destinations = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/metric.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/metric.proto new file mode 100644 index 00000000..9bf043c4 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/metric.proto @@ -0,0 +1,268 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/label.proto"; +import "google/api/launch_stage.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/metric;metric"; +option java_multiple_files = true; +option java_outer_classname = "MetricProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines a metric type and its schema. Once a metric descriptor is created, +// deleting or altering it stops data collection and makes the metric type's +// existing data unusable. +// +message MetricDescriptor { + // The kind of measurement. It describes how the data is reported. + // For information on setting the start time and end time based on + // the MetricKind, see [TimeInterval][google.monitoring.v3.TimeInterval]. + enum MetricKind { + // Do not use this default value. + METRIC_KIND_UNSPECIFIED = 0; + + // An instantaneous measurement of a value. + GAUGE = 1; + + // The change in a value during a time interval. + DELTA = 2; + + // A value accumulated over a time interval. Cumulative + // measurements in a time series should have the same start time + // and increasing end times, until an event resets the cumulative + // value to zero and sets a new start time for the following + // points. + CUMULATIVE = 3; + } + + // The value type of a metric. + enum ValueType { + // Do not use this default value. + VALUE_TYPE_UNSPECIFIED = 0; + + // The value is a boolean. + // This value type can be used only if the metric kind is `GAUGE`. + BOOL = 1; + + // The value is a signed 64-bit integer. + INT64 = 2; + + // The value is a double precision floating point number. + DOUBLE = 3; + + // The value is a text string. + // This value type can be used only if the metric kind is `GAUGE`. + STRING = 4; + + // The value is a [`Distribution`][google.api.Distribution]. + DISTRIBUTION = 5; + + // The value is money. + MONEY = 6; + } + + // Additional annotations that can be used to guide the usage of a metric. + message MetricDescriptorMetadata { + // Deprecated. Must use the + // [MetricDescriptor.launch_stage][google.api.MetricDescriptor.launch_stage] + // instead. + LaunchStage launch_stage = 1 [deprecated = true]; + + // The sampling period of metric data points. For metrics which are written + // periodically, consecutive data points are stored at this time interval, + // excluding data loss due to errors. Metrics with a higher granularity have + // a smaller sampling period. + google.protobuf.Duration sample_period = 2; + + // The delay of data points caused by ingestion. Data points older than this + // age are guaranteed to be ingested and available to be read, excluding + // data loss due to errors. + google.protobuf.Duration ingest_delay = 3; + } + + // The resource name of the metric descriptor. + string name = 1; + + // The metric type, including its DNS name prefix. The type is not + // URL-encoded. All user-defined metric types have the DNS name + // `custom.googleapis.com` or `external.googleapis.com`. Metric types should + // use a natural hierarchical grouping. For example: + // + // "custom.googleapis.com/invoice/paid/amount" + // "external.googleapis.com/prometheus/up" + // "appengine.googleapis.com/http/server/response_latencies" + string type = 8; + + // The set of labels that can be used to describe a specific + // instance of this metric type. For example, the + // `appengine.googleapis.com/http/server/response_latencies` metric + // type has a label for the HTTP response code, `response_code`, so + // you can look at latencies for successful responses or just + // for responses that failed. + repeated LabelDescriptor labels = 2; + + // Whether the metric records instantaneous values, changes to a value, etc. + // Some combinations of `metric_kind` and `value_type` might not be supported. + MetricKind metric_kind = 3; + + // Whether the measurement is an integer, a floating-point number, etc. + // Some combinations of `metric_kind` and `value_type` might not be supported. + ValueType value_type = 4; + + // The units in which the metric value is reported. It is only applicable + // if the `value_type` is `INT64`, `DOUBLE`, or `DISTRIBUTION`. The `unit` + // defines the representation of the stored metric values. + // + // Different systems might scale the values to be more easily displayed (so a + // value of `0.02kBy` _might_ be displayed as `20By`, and a value of + // `3523kBy` _might_ be displayed as `3.5MBy`). However, if the `unit` is + // `kBy`, then the value of the metric is always in thousands of bytes, no + // matter how it might be displayed. + // + // If you want a custom metric to record the exact number of CPU-seconds used + // by a job, you can create an `INT64 CUMULATIVE` metric whose `unit` is + // `s{CPU}` (or equivalently `1s{CPU}` or just `s`). If the job uses 12,005 + // CPU-seconds, then the value is written as `12005`. + // + // Alternatively, if you want a custom metric to record data in a more + // granular way, you can create a `DOUBLE CUMULATIVE` metric whose `unit` is + // `ks{CPU}`, and then write the value `12.005` (which is `12005/1000`), + // or use `Kis{CPU}` and write `11.723` (which is `12005/1024`). + // + // The supported units are a subset of [The Unified Code for Units of + // Measure](https://unitsofmeasure.org/ucum.html) standard: + // + // **Basic units (UNIT)** + // + // * `bit` bit + // * `By` byte + // * `s` second + // * `min` minute + // * `h` hour + // * `d` day + // * `1` dimensionless + // + // **Prefixes (PREFIX)** + // + // * `k` kilo (10^3) + // * `M` mega (10^6) + // * `G` giga (10^9) + // * `T` tera (10^12) + // * `P` peta (10^15) + // * `E` exa (10^18) + // * `Z` zetta (10^21) + // * `Y` yotta (10^24) + // + // * `m` milli (10^-3) + // * `u` micro (10^-6) + // * `n` nano (10^-9) + // * `p` pico (10^-12) + // * `f` femto (10^-15) + // * `a` atto (10^-18) + // * `z` zepto (10^-21) + // * `y` yocto (10^-24) + // + // * `Ki` kibi (2^10) + // * `Mi` mebi (2^20) + // * `Gi` gibi (2^30) + // * `Ti` tebi (2^40) + // * `Pi` pebi (2^50) + // + // **Grammar** + // + // The grammar also includes these connectors: + // + // * `/` division or ratio (as an infix operator). For examples, + // `kBy/{email}` or `MiBy/10ms` (although you should almost never + // have `/s` in a metric `unit`; rates should always be computed at + // query time from the underlying cumulative or delta value). + // * `.` multiplication or composition (as an infix operator). For + // examples, `GBy.d` or `k{watt}.h`. + // + // The grammar for a unit is as follows: + // + // Expression = Component { "." Component } { "/" Component } ; + // + // Component = ( [ PREFIX ] UNIT | "%" ) [ Annotation ] + // | Annotation + // | "1" + // ; + // + // Annotation = "{" NAME "}" ; + // + // Notes: + // + // * `Annotation` is just a comment if it follows a `UNIT`. If the annotation + // is used alone, then the unit is equivalent to `1`. For examples, + // `{request}/s == 1/s`, `By{transmitted}/s == By/s`. + // * `NAME` is a sequence of non-blank printable ASCII characters not + // containing `{` or `}`. + // * `1` represents a unitary [dimensionless + // unit](https://en.wikipedia.org/wiki/Dimensionless_quantity) of 1, such + // as in `1/s`. It is typically used when none of the basic units are + // appropriate. For example, "new users per day" can be represented as + // `1/d` or `{new-users}/d` (and a metric value `5` would mean "5 new + // users). Alternatively, "thousands of page views per day" would be + // represented as `1000/d` or `k1/d` or `k{page_views}/d` (and a metric + // value of `5.3` would mean "5300 page views per day"). + // * `%` represents dimensionless value of 1/100, and annotates values giving + // a percentage (so the metric values are typically in the range of 0..100, + // and a metric value `3` means "3 percent"). + // * `10^2.%` indicates a metric contains a ratio, typically in the range + // 0..1, that will be multiplied by 100 and displayed as a percentage + // (so a metric value `0.03` means "3 percent"). + string unit = 5; + + // A detailed description of the metric, which can be used in documentation. + string description = 6; + + // A concise name for the metric, which can be displayed in user interfaces. + // Use sentence case without an ending period, for example "Request count". + // This field is optional but it is recommended to be set for any metrics + // associated with user-visible concepts, such as Quota. + string display_name = 7; + + // Optional. Metadata which can be used to guide usage of the metric. + MetricDescriptorMetadata metadata = 10; + + // Optional. The launch stage of the metric definition. + LaunchStage launch_stage = 12; + + // Read-only. If present, then a [time + // series][google.monitoring.v3.TimeSeries], which is identified partially by + // a metric type and a + // [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor], that + // is associated with this metric type can only be associated with one of the + // monitored resource types listed here. + repeated string monitored_resource_types = 13; +} + +// A specific metric, identified by specifying values for all of the +// labels of a [`MetricDescriptor`][google.api.MetricDescriptor]. +message Metric { + // An existing metric type, see + // [google.api.MetricDescriptor][google.api.MetricDescriptor]. For example, + // `custom.googleapis.com/invoice/paid/amount`. + string type = 3; + + // The set of label values that uniquely identify this metric. All + // labels listed in the `MetricDescriptor` must be assigned values. + map labels = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitored_resource.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitored_resource.proto new file mode 100644 index 00000000..c6f97592 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitored_resource.proto @@ -0,0 +1,130 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/label.proto"; +import "google/api/launch_stage.proto"; +import "google/protobuf/struct.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/monitoredres;monitoredres"; +option java_multiple_files = true; +option java_outer_classname = "MonitoredResourceProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// An object that describes the schema of a +// [MonitoredResource][google.api.MonitoredResource] object using a type name +// and a set of labels. For example, the monitored resource descriptor for +// Google Compute Engine VM instances has a type of +// `"gce_instance"` and specifies the use of the labels `"instance_id"` and +// `"zone"` to identify particular VM instances. +// +// Different APIs can support different monitored resource types. APIs generally +// provide a `list` method that returns the monitored resource descriptors used +// by the API. +// +message MonitoredResourceDescriptor { + // Optional. The resource name of the monitored resource descriptor: + // `"projects/{project_id}/monitoredResourceDescriptors/{type}"` where + // {type} is the value of the `type` field in this object and + // {project_id} is a project ID that provides API-specific context for + // accessing the type. APIs that do not use project information can use the + // resource name format `"monitoredResourceDescriptors/{type}"`. + string name = 5; + + // Required. The monitored resource type. For example, the type + // `"cloudsql_database"` represents databases in Google Cloud SQL. + // For a list of types, see [Monitoring resource + // types](https://cloud.google.com/monitoring/api/resources) + // and [Logging resource + // types](https://cloud.google.com/logging/docs/api/v2/resource-list). + string type = 1; + + // Optional. A concise name for the monitored resource type that might be + // displayed in user interfaces. It should be a Title Cased Noun Phrase, + // without any article or other determiners. For example, + // `"Google Cloud SQL Database"`. + string display_name = 2; + + // Optional. A detailed description of the monitored resource type that might + // be used in documentation. + string description = 3; + + // Required. A set of labels used to describe instances of this monitored + // resource type. For example, an individual Google Cloud SQL database is + // identified by values for the labels `"database_id"` and `"zone"`. + repeated LabelDescriptor labels = 4; + + // Optional. The launch stage of the monitored resource definition. + LaunchStage launch_stage = 7; +} + +// An object representing a resource that can be used for monitoring, logging, +// billing, or other purposes. Examples include virtual machine instances, +// databases, and storage devices such as disks. The `type` field identifies a +// [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor] object +// that describes the resource's schema. Information in the `labels` field +// identifies the actual resource and its attributes according to the schema. +// For example, a particular Compute Engine VM instance could be represented by +// the following object, because the +// [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor] for +// `"gce_instance"` has labels +// `"project_id"`, `"instance_id"` and `"zone"`: +// +// { "type": "gce_instance", +// "labels": { "project_id": "my-project", +// "instance_id": "12345678901234", +// "zone": "us-central1-a" }} +message MonitoredResource { + // Required. The monitored resource type. This field must match + // the `type` field of a + // [MonitoredResourceDescriptor][google.api.MonitoredResourceDescriptor] + // object. For example, the type of a Compute Engine VM instance is + // `gce_instance`. Some descriptors include the service name in the type; for + // example, the type of a Datastream stream is + // `datastream.googleapis.com/Stream`. + string type = 1; + + // Required. Values for all of the labels listed in the associated monitored + // resource descriptor. For example, Compute Engine VM instances use the + // labels `"project_id"`, `"instance_id"`, and `"zone"`. + map labels = 2; +} + +// Auxiliary metadata for a [MonitoredResource][google.api.MonitoredResource] +// object. [MonitoredResource][google.api.MonitoredResource] objects contain the +// minimum set of information to uniquely identify a monitored resource +// instance. There is some other useful auxiliary metadata. Monitoring and +// Logging use an ingestion pipeline to extract metadata for cloud resources of +// all types, and store the metadata in this message. +message MonitoredResourceMetadata { + // Output only. Values for predefined system metadata labels. + // System labels are a kind of metadata extracted by Google, including + // "machine_image", "vpc", "subnet_id", + // "security_group", "name", etc. + // System label values can be only strings, Boolean values, or a list of + // strings. For example: + // + // { "name": "my-test-instance", + // "security_group": ["a", "b", "c"], + // "spot_instance": false } + google.protobuf.Struct system_labels = 1; + + // Output only. A map of user-defined metadata labels. + map user_labels = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitoring.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitoring.proto new file mode 100644 index 00000000..753703e5 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/monitoring.proto @@ -0,0 +1,107 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "MonitoringProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Monitoring configuration of the service. +// +// The example below shows how to configure monitored resources and metrics +// for monitoring. In the example, a monitored resource and two metrics are +// defined. The `library.googleapis.com/book/returned_count` metric is sent +// to both producer and consumer projects, whereas the +// `library.googleapis.com/book/num_overdue` metric is only sent to the +// consumer project. +// +// monitored_resources: +// - type: library.googleapis.com/Branch +// display_name: "Library Branch" +// description: "A branch of a library." +// launch_stage: GA +// labels: +// - key: resource_container +// description: "The Cloud container (ie. project id) for the Branch." +// - key: location +// description: "The location of the library branch." +// - key: branch_id +// description: "The id of the branch." +// metrics: +// - name: library.googleapis.com/book/returned_count +// display_name: "Books Returned" +// description: "The count of books that have been returned." +// launch_stage: GA +// metric_kind: DELTA +// value_type: INT64 +// unit: "1" +// labels: +// - key: customer_id +// description: "The id of the customer." +// - name: library.googleapis.com/book/num_overdue +// display_name: "Books Overdue" +// description: "The current number of overdue books." +// launch_stage: GA +// metric_kind: GAUGE +// value_type: INT64 +// unit: "1" +// labels: +// - key: customer_id +// description: "The id of the customer." +// monitoring: +// producer_destinations: +// - monitored_resource: library.googleapis.com/Branch +// metrics: +// - library.googleapis.com/book/returned_count +// consumer_destinations: +// - monitored_resource: library.googleapis.com/Branch +// metrics: +// - library.googleapis.com/book/returned_count +// - library.googleapis.com/book/num_overdue +message Monitoring { + // Configuration of a specific monitoring destination (the producer project + // or the consumer project). + message MonitoringDestination { + // The monitored resource type. The type must be defined in + // [Service.monitored_resources][google.api.Service.monitored_resources] + // section. + string monitored_resource = 1; + + // Types of the metrics to report to this monitoring destination. + // Each type must be defined in + // [Service.metrics][google.api.Service.metrics] section. + repeated string metrics = 2; + } + + // Monitoring configurations for sending metrics to the producer project. + // There can be multiple producer destinations. A monitored resource type may + // appear in multiple monitoring destinations if different aggregations are + // needed for different sets of metrics associated with that monitored + // resource type. A monitored resource and metric pair may only be used once + // in the Monitoring configuration. + repeated MonitoringDestination producer_destinations = 1; + + // Monitoring configurations for sending metrics to the consumer project. + // There can be multiple consumer destinations. A monitored resource type may + // appear in multiple monitoring destinations if different aggregations are + // needed for different sets of metrics associated with that monitored + // resource type. A monitored resource and metric pair may only be used once + // in the Monitoring configuration. + repeated MonitoringDestination consumer_destinations = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/policy.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/policy.proto new file mode 100644 index 00000000..dd202bc8 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/policy.proto @@ -0,0 +1,85 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "PolicyProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Provides `google.api.field_policy` annotation at proto fields. +extend google.protobuf.FieldOptions { + // See [FieldPolicy][]. + FieldPolicy field_policy = 158361448; +} + +// Provides `google.api.method_policy` annotation at proto methods. +extend google.protobuf.MethodOptions { + // See [MethodPolicy][]. + MethodPolicy method_policy = 161893301; +} + +// Google API Policy Annotation +// +// This message defines a simple API policy annotation that can be used to +// annotate API request and response message fields with applicable policies. +// One field may have multiple applicable policies that must all be satisfied +// before a request can be processed. This policy annotation is used to +// generate the overall policy that will be used for automatic runtime +// policy enforcement and documentation generation. +message FieldPolicy { + // Selects one or more request or response message fields to apply this + // `FieldPolicy`. + // + // When a `FieldPolicy` is used in proto annotation, the selector must + // be left as empty. The service config generator will automatically fill + // the correct value. + // + // When a `FieldPolicy` is used in service config, the selector must be a + // comma-separated string with valid request or response field paths, + // such as "foo.bar" or "foo.bar,foo.baz". + string selector = 1; + + // Specifies the required permission(s) for the resource referred to by the + // field. It requires the field contains a valid resource reference, and + // the request must pass the permission checks to proceed. For example, + // "resourcemanager.projects.get". + string resource_permission = 2; + + // Specifies the resource type for the resource referred to by the field. + string resource_type = 3; +} + +// Defines policies applying to an RPC method. +message MethodPolicy { + // Selects a method to which these policies should be enforced, for example, + // "google.pubsub.v1.Subscriber.CreateSubscription". + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + // + // NOTE: This field must not be set in the proto annotation. It will be + // automatically filled by the service config compiler . + string selector = 9; + + // Policies that are applicable to the request message. + repeated FieldPolicy request_policies = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/quota.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/quota.proto new file mode 100644 index 00000000..7ccc102f --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/quota.proto @@ -0,0 +1,184 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "QuotaProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Quota configuration helps to achieve fairness and budgeting in service +// usage. +// +// The metric based quota configuration works this way: +// - The service configuration defines a set of metrics. +// - For API calls, the quota.metric_rules maps methods to metrics with +// corresponding costs. +// - The quota.limits defines limits on the metrics, which will be used for +// quota checks at runtime. +// +// An example quota configuration in yaml format: +// +// quota: +// limits: +// +// - name: apiWriteQpsPerProject +// metric: library.googleapis.com/write_calls +// unit: "1/min/{project}" # rate limit for consumer projects +// values: +// STANDARD: 10000 +// +// +// (The metric rules bind all methods to the read_calls metric, +// except for the UpdateBook and DeleteBook methods. These two methods +// are mapped to the write_calls metric, with the UpdateBook method +// consuming at twice rate as the DeleteBook method.) +// metric_rules: +// - selector: "*" +// metric_costs: +// library.googleapis.com/read_calls: 1 +// - selector: google.example.library.v1.LibraryService.UpdateBook +// metric_costs: +// library.googleapis.com/write_calls: 2 +// - selector: google.example.library.v1.LibraryService.DeleteBook +// metric_costs: +// library.googleapis.com/write_calls: 1 +// +// Corresponding Metric definition: +// +// metrics: +// - name: library.googleapis.com/read_calls +// display_name: Read requests +// metric_kind: DELTA +// value_type: INT64 +// +// - name: library.googleapis.com/write_calls +// display_name: Write requests +// metric_kind: DELTA +// value_type: INT64 +// +// +message Quota { + // List of QuotaLimit definitions for the service. + repeated QuotaLimit limits = 3; + + // List of MetricRule definitions, each one mapping a selected method to one + // or more metrics. + repeated MetricRule metric_rules = 4; +} + +// Bind API methods to metrics. Binding a method to a metric causes that +// metric's configured quota behaviors to apply to the method call. +message MetricRule { + // Selects the methods to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // Metrics to update when the selected methods are called, and the associated + // cost applied to each metric. + // + // The key of the map is the metric name, and the values are the amount + // increased for the metric against which the quota limits are defined. + // The value must not be negative. + map metric_costs = 2; +} + +// `QuotaLimit` defines a specific limit that applies over a specified duration +// for a limit type. There can be at most one limit for a duration and limit +// type combination defined within a `QuotaGroup`. +message QuotaLimit { + // Name of the quota limit. + // + // The name must be provided, and it must be unique within the service. The + // name can only include alphanumeric characters as well as '-'. + // + // The maximum length of the limit name is 64 characters. + string name = 6; + + // Optional. User-visible, extended description for this quota limit. + // Should be used only when more context is needed to understand this limit + // than provided by the limit's display name (see: `display_name`). + string description = 2; + + // Default number of tokens that can be consumed during the specified + // duration. This is the number of tokens assigned when a client + // application developer activates the service for his/her project. + // + // Specifying a value of 0 will block all requests. This can be used if you + // are provisioning quota to selected consumers and blocking others. + // Similarly, a value of -1 will indicate an unlimited quota. No other + // negative values are allowed. + // + // Used by group-based quotas only. + int64 default_limit = 3; + + // Maximum number of tokens that can be consumed during the specified + // duration. Client application developers can override the default limit up + // to this maximum. If specified, this value cannot be set to a value less + // than the default limit. If not specified, it is set to the default limit. + // + // To allow clients to apply overrides with no upper bound, set this to -1, + // indicating unlimited maximum quota. + // + // Used by group-based quotas only. + int64 max_limit = 4; + + // Free tier value displayed in the Developers Console for this limit. + // The free tier is the number of tokens that will be subtracted from the + // billed amount when billing is enabled. + // This field can only be set on a limit with duration "1d", in a billable + // group; it is invalid on any other limit. If this field is not set, it + // defaults to 0, indicating that there is no free tier for this service. + // + // Used by group-based quotas only. + int64 free_tier = 7; + + // Duration of this limit in textual notation. Must be "100s" or "1d". + // + // Used by group-based quotas only. + string duration = 5; + + // The name of the metric this quota limit applies to. The quota limits with + // the same metric will be checked together during runtime. The metric must be + // defined within the service config. + string metric = 8; + + // Specify the unit of the quota limit. It uses the same syntax as + // [Metric.unit][]. The supported unit kinds are determined by the quota + // backend system. + // + // Here are some examples: + // * "1/min/{project}" for quota per minute per project. + // + // Note: the order of unit components is insignificant. + // The "1" at the beginning is required to follow the metric unit syntax. + string unit = 9; + + // Tiered limit values. You must specify this as a key:value pair, with an + // integer value that is the maximum number of requests allowed for the + // specified unit. Currently only STANDARD is supported. + map values = 10; + + // User-visible display name for this limit. + // Optional. If not set, the UI will provide a default display name based on + // the quota configuration. This field can be used to override the default + // display name generated from the configuration. + string display_name = 12; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/resource.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/resource.proto new file mode 100644 index 00000000..bf0cbec5 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/resource.proto @@ -0,0 +1,238 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "ResourceProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.FieldOptions { + // An annotation that describes a resource reference, see + // [ResourceReference][]. + google.api.ResourceReference resource_reference = 1055; +} + +extend google.protobuf.FileOptions { + // An annotation that describes a resource definition without a corresponding + // message; see [ResourceDescriptor][]. + repeated google.api.ResourceDescriptor resource_definition = 1053; +} + +extend google.protobuf.MessageOptions { + // An annotation that describes a resource definition, see + // [ResourceDescriptor][]. + google.api.ResourceDescriptor resource = 1053; +} + +// A simple descriptor of a resource type. +// +// ResourceDescriptor annotates a resource message (either by means of a +// protobuf annotation or use in the service config), and associates the +// resource's schema, the resource type, and the pattern of the resource name. +// +// Example: +// +// message Topic { +// // Indicates this message defines a resource schema. +// // Declares the resource type in the format of {service}/{kind}. +// // For Kubernetes resources, the format is {api group}/{kind}. +// option (google.api.resource) = { +// type: "pubsub.googleapis.com/Topic" +// pattern: "projects/{project}/topics/{topic}" +// }; +// } +// +// The ResourceDescriptor Yaml config will look like: +// +// resources: +// - type: "pubsub.googleapis.com/Topic" +// pattern: "projects/{project}/topics/{topic}" +// +// Sometimes, resources have multiple patterns, typically because they can +// live under multiple parents. +// +// Example: +// +// message LogEntry { +// option (google.api.resource) = { +// type: "logging.googleapis.com/LogEntry" +// pattern: "projects/{project}/logs/{log}" +// pattern: "folders/{folder}/logs/{log}" +// pattern: "organizations/{organization}/logs/{log}" +// pattern: "billingAccounts/{billing_account}/logs/{log}" +// }; +// } +// +// The ResourceDescriptor Yaml config will look like: +// +// resources: +// - type: 'logging.googleapis.com/LogEntry' +// pattern: "projects/{project}/logs/{log}" +// pattern: "folders/{folder}/logs/{log}" +// pattern: "organizations/{organization}/logs/{log}" +// pattern: "billingAccounts/{billing_account}/logs/{log}" +message ResourceDescriptor { + // A description of the historical or future-looking state of the + // resource pattern. + enum History { + // The "unset" value. + HISTORY_UNSPECIFIED = 0; + + // The resource originally had one pattern and launched as such, and + // additional patterns were added later. + ORIGINALLY_SINGLE_PATTERN = 1; + + // The resource has one pattern, but the API owner expects to add more + // later. (This is the inverse of ORIGINALLY_SINGLE_PATTERN, and prevents + // that from being necessary once there are multiple patterns.) + FUTURE_MULTI_PATTERN = 2; + } + + // A flag representing a specific style that a resource claims to conform to. + enum Style { + // The unspecified value. Do not use. + STYLE_UNSPECIFIED = 0; + + // This resource is intended to be "declarative-friendly". + // + // Declarative-friendly resources must be more strictly consistent, and + // setting this to true communicates to tools that this resource should + // adhere to declarative-friendly expectations. + // + // Note: This is used by the API linter (linter.aip.dev) to enable + // additional checks. + DECLARATIVE_FRIENDLY = 1; + } + + // The resource type. It must be in the format of + // {service_name}/{resource_type_kind}. The `resource_type_kind` must be + // singular and must not include version numbers. + // + // Example: `storage.googleapis.com/Bucket` + // + // The value of the resource_type_kind must follow the regular expression + // /[A-Za-z][a-zA-Z0-9]+/. It should start with an upper case character and + // should use PascalCase (UpperCamelCase). The maximum number of + // characters allowed for the `resource_type_kind` is 100. + string type = 1; + + // Optional. The relative resource name pattern associated with this resource + // type. The DNS prefix of the full resource name shouldn't be specified here. + // + // The path pattern must follow the syntax, which aligns with HTTP binding + // syntax: + // + // Template = Segment { "/" Segment } ; + // Segment = LITERAL | Variable ; + // Variable = "{" LITERAL "}" ; + // + // Examples: + // + // - "projects/{project}/topics/{topic}" + // - "projects/{project}/knowledgeBases/{knowledge_base}" + // + // The components in braces correspond to the IDs for each resource in the + // hierarchy. It is expected that, if multiple patterns are provided, + // the same component name (e.g. "project") refers to IDs of the same + // type of resource. + repeated string pattern = 2; + + // Optional. The field on the resource that designates the resource name + // field. If omitted, this is assumed to be "name". + string name_field = 3; + + // Optional. The historical or future-looking state of the resource pattern. + // + // Example: + // + // // The InspectTemplate message originally only supported resource + // // names with organization, and project was added later. + // message InspectTemplate { + // option (google.api.resource) = { + // type: "dlp.googleapis.com/InspectTemplate" + // pattern: + // "organizations/{organization}/inspectTemplates/{inspect_template}" + // pattern: "projects/{project}/inspectTemplates/{inspect_template}" + // history: ORIGINALLY_SINGLE_PATTERN + // }; + // } + History history = 4; + + // The plural name used in the resource name and permission names, such as + // 'projects' for the resource name of 'projects/{project}' and the permission + // name of 'cloudresourcemanager.googleapis.com/projects.get'. It is the same + // concept of the `plural` field in k8s CRD spec + // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ + // + // Note: The plural form is required even for singleton resources. See + // https://aip.dev/156 + string plural = 5; + + // The same concept of the `singular` field in k8s CRD spec + // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ + // Such as "project" for the `resourcemanager.googleapis.com/Project` type. + string singular = 6; + + // Style flag(s) for this resource. + // These indicate that a resource is expected to conform to a given + // style. See the specific style flags for additional information. + repeated Style style = 10; +} + +// Defines a proto annotation that describes a string field that refers to +// an API resource. +message ResourceReference { + // The resource type that the annotated field references. + // + // Example: + // + // message Subscription { + // string topic = 2 [(google.api.resource_reference) = { + // type: "pubsub.googleapis.com/Topic" + // }]; + // } + // + // Occasionally, a field may reference an arbitrary resource. In this case, + // APIs use the special value * in their resource reference. + // + // Example: + // + // message GetIamPolicyRequest { + // string resource = 2 [(google.api.resource_reference) = { + // type: "*" + // }]; + // } + string type = 1; + + // The resource type of a child collection that the annotated field + // references. This is useful for annotating the `parent` field that + // doesn't have a fixed resource type. + // + // Example: + // + // message ListLogEntriesRequest { + // string parent = 1 [(google.api.resource_reference) = { + // child_type: "logging.googleapis.com/LogEntry" + // }; + // } + string child_type = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/routing.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/routing.proto new file mode 100644 index 00000000..b35289be --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/routing.proto @@ -0,0 +1,461 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "RoutingProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See RoutingRule. + google.api.RoutingRule routing = 72295729; +} + +// Specifies the routing information that should be sent along with the request +// in the form of routing header. +// **NOTE:** All service configuration rules follow the "last one wins" order. +// +// The examples below will apply to an RPC which has the following request type: +// +// Message Definition: +// +// message Request { +// // The name of the Table +// // Values can be of the following formats: +// // - `projects//tables/` +// // - `projects//instances//tables/
    ` +// // - `region//zones//tables/
    ` +// string table_name = 1; +// +// // This value specifies routing for replication. +// // It can be in the following formats: +// // - `profiles/` +// // - a legacy `profile_id` that can be any string +// string app_profile_id = 2; +// } +// +// Example message: +// +// { +// table_name: projects/proj_foo/instances/instance_bar/table/table_baz, +// app_profile_id: profiles/prof_qux +// } +// +// The routing header consists of one or multiple key-value pairs. Every key +// and value must be percent-encoded, and joined together in the format of +// `key1=value1&key2=value2`. +// In the examples below I am skipping the percent-encoding for readablity. +// +// Example 1 +// +// Extracting a field from the request to put into the routing header +// unchanged, with the key equal to the field name. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `app_profile_id`. +// routing_parameters { +// field: "app_profile_id" +// } +// }; +// +// result: +// +// x-goog-request-params: app_profile_id=profiles/prof_qux +// +// Example 2 +// +// Extracting a field from the request to put into the routing header +// unchanged, with the key different from the field name. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `app_profile_id`, but name it `routing_id` in the header. +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// }; +// +// result: +// +// x-goog-request-params: routing_id=profiles/prof_qux +// +// Example 3 +// +// Extracting a field from the request to put into the routing +// header, while matching a path template syntax on the field's value. +// +// NB: it is more useful to send nothing than to send garbage for the purpose +// of dynamic routing, since garbage pollutes cache. Thus the matching. +// +// Sub-example 3a +// +// The field matches the template. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `table_name`, if it's well-formed (with project-based +// // syntax). +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=projects/*/instances/*/**}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// table_name=projects/proj_foo/instances/instance_bar/table/table_baz +// +// Sub-example 3b +// +// The field does not match the template. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `table_name`, if it's well-formed (with region-based +// // syntax). +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=regions/*/zones/*/**}" +// } +// }; +// +// result: +// +// +// +// Sub-example 3c +// +// Multiple alternative conflictingly named path templates are +// specified. The one that matches is used to construct the header. +// +// annotation: +// +// option (google.api.routing) = { +// // Take the `table_name`, if it's well-formed, whether +// // using the region- or projects-based syntax. +// +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=regions/*/zones/*/**}" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{table_name=projects/*/instances/*/**}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// table_name=projects/proj_foo/instances/instance_bar/table/table_baz +// +// Example 4 +// +// Extracting a single routing header key-value pair by matching a +// template syntax on (a part of) a single request field. +// +// annotation: +// +// option (google.api.routing) = { +// // Take just the project id from the `table_name` field. +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// }; +// +// result: +// +// x-goog-request-params: routing_id=projects/proj_foo +// +// Example 5 +// +// Extracting a single routing header key-value pair by matching +// several conflictingly named path templates on (parts of) a single request +// field. The last template to match "wins" the conflict. +// +// annotation: +// +// option (google.api.routing) = { +// // If the `table_name` does not have instances information, +// // take just the project id for routing. +// // Otherwise take project + instance. +// +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*/instances/*}/**" +// } +// }; +// +// result: +// +// x-goog-request-params: +// routing_id=projects/proj_foo/instances/instance_bar +// +// Example 6 +// +// Extracting multiple routing header key-value pairs by matching +// several non-conflicting path templates on (parts of) a single request field. +// +// Sub-example 6a +// +// Make the templates strict, so that if the `table_name` does not +// have an instance information, nothing is sent. +// +// annotation: +// +// option (google.api.routing) = { +// // The routing code needs two keys instead of one composite +// // but works only for the tables with the "project-instance" name +// // syntax. +// +// routing_parameters { +// field: "table_name" +// path_template: "{project_id=projects/*}/instances/*/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "projects/*/{instance_id=instances/*}/**" +// } +// }; +// +// result: +// +// x-goog-request-params: +// project_id=projects/proj_foo&instance_id=instances/instance_bar +// +// Sub-example 6b +// +// Make the templates loose, so that if the `table_name` does not +// have an instance information, just the project id part is sent. +// +// annotation: +// +// option (google.api.routing) = { +// // The routing code wants two keys instead of one composite +// // but will work with just the `project_id` for tables without +// // an instance in the `table_name`. +// +// routing_parameters { +// field: "table_name" +// path_template: "{project_id=projects/*}/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "projects/*/{instance_id=instances/*}/**" +// } +// }; +// +// result (is the same as 6a for our example message because it has the instance +// information): +// +// x-goog-request-params: +// project_id=projects/proj_foo&instance_id=instances/instance_bar +// +// Example 7 +// +// Extracting multiple routing header key-value pairs by matching +// several path templates on multiple request fields. +// +// NB: note that here there is no way to specify sending nothing if one of the +// fields does not match its template. E.g. if the `table_name` is in the wrong +// format, the `project_id` will not be sent, but the `routing_id` will be. +// The backend routing code has to be aware of that and be prepared to not +// receive a full complement of keys if it expects multiple. +// +// annotation: +// +// option (google.api.routing) = { +// // The routing needs both `project_id` and `routing_id` +// // (from the `app_profile_id` field) for routing. +// +// routing_parameters { +// field: "table_name" +// path_template: "{project_id=projects/*}/**" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// project_id=projects/proj_foo&routing_id=profiles/prof_qux +// +// Example 8 +// +// Extracting a single routing header key-value pair by matching +// several conflictingly named path templates on several request fields. The +// last template to match "wins" the conflict. +// +// annotation: +// +// option (google.api.routing) = { +// // The `routing_id` can be a project id or a region id depending on +// // the table name format, but only if the `app_profile_id` is not set. +// // If `app_profile_id` is set it should be used instead. +// +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=regions/*}/**" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// }; +// +// result: +// +// x-goog-request-params: routing_id=profiles/prof_qux +// +// Example 9 +// +// Bringing it all together. +// +// annotation: +// +// option (google.api.routing) = { +// // For routing both `table_location` and a `routing_id` are needed. +// // +// // table_location can be either an instance id or a region+zone id. +// // +// // For `routing_id`, take the value of `app_profile_id` +// // - If it's in the format `profiles/`, send +// // just the `` part. +// // - If it's any other literal, send it as is. +// // If the `app_profile_id` is empty, and the `table_name` starts with +// // the project_id, send that instead. +// +// routing_parameters { +// field: "table_name" +// path_template: "projects/*/{table_location=instances/*}/tables/*" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{table_location=regions/*/zones/*}/tables/*" +// } +// routing_parameters { +// field: "table_name" +// path_template: "{routing_id=projects/*}/**" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "{routing_id=**}" +// } +// routing_parameters { +// field: "app_profile_id" +// path_template: "profiles/{routing_id=*}" +// } +// }; +// +// result: +// +// x-goog-request-params: +// table_location=instances/instance_bar&routing_id=prof_qux +message RoutingRule { + // A collection of Routing Parameter specifications. + // **NOTE:** If multiple Routing Parameters describe the same key + // (via the `path_template` field or via the `field` field when + // `path_template` is not provided), "last one wins" rule + // determines which Parameter gets used. + // See the examples for more details. + repeated RoutingParameter routing_parameters = 2; +} + +// A projection from an input message to the GRPC or REST header. +message RoutingParameter { + // A request field to extract the header key-value pair from. + string field = 1; + + // A pattern matching the key-value field. Optional. + // If not specified, the whole field specified in the `field` field will be + // taken as value, and its name used as key. If specified, it MUST contain + // exactly one named segment (along with any number of unnamed segments) The + // pattern will be matched over the field specified in the `field` field, then + // if the match is successful: + // - the name of the single named segment will be used as a header name, + // - the match value of the segment will be used as a header value; + // if the match is NOT successful, nothing will be sent. + // + // Example: + // + // -- This is a field in the request message + // | that the header value will be extracted from. + // | + // | -- This is the key name in the + // | | routing header. + // V | + // field: "table_name" v + // path_template: "projects/*/{table_location=instances/*}/tables/*" + // ^ ^ + // | | + // In the {} brackets is the pattern that -- | + // specifies what to extract from the | + // field as a value to be sent. | + // | + // The string in the field must match the whole pattern -- + // before brackets, inside brackets, after brackets. + // + // When looking at this specific example, we can see that: + // - A key-value pair with the key `table_location` + // and the value matching `instances/*` should be added + // to the x-goog-request-params routing header. + // - The value is extracted from the request message's `table_name` field + // if it matches the full pattern specified: + // `projects/*/instances/*/tables/*`. + // + // **NB:** If the `path_template` field is not provided, the key name is + // equal to the field name, and the whole field should be sent as a value. + // This makes the pattern for the field and the value functionally equivalent + // to `**`, and the configuration + // + // { + // field: "table_name" + // } + // + // is a functionally equivalent shorthand to: + // + // { + // field: "table_name" + // path_template: "{table_name=**}" + // } + // + // See Example 1 for more details. + string path_template = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/service.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/service.proto new file mode 100644 index 00000000..3de5b667 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/service.proto @@ -0,0 +1,191 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/auth.proto"; +import "google/api/backend.proto"; +import "google/api/billing.proto"; +import "google/api/client.proto"; +import "google/api/context.proto"; +import "google/api/control.proto"; +import "google/api/documentation.proto"; +import "google/api/endpoint.proto"; +import "google/api/http.proto"; +import "google/api/log.proto"; +import "google/api/logging.proto"; +import "google/api/metric.proto"; +import "google/api/monitored_resource.proto"; +import "google/api/monitoring.proto"; +import "google/api/quota.proto"; +import "google/api/source_info.proto"; +import "google/api/system_parameter.proto"; +import "google/api/usage.proto"; +import "google/protobuf/api.proto"; +import "google/protobuf/type.proto"; +import "google/protobuf/wrappers.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "ServiceProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// `Service` is the root object of Google API service configuration (service +// config). It describes the basic information about a logical service, +// such as the service name and the user-facing title, and delegates other +// aspects to sub-sections. Each sub-section is either a proto message or a +// repeated proto message that configures a specific aspect, such as auth. +// For more information, see each proto message definition. +// +// Example: +// +// type: google.api.Service +// name: calendar.googleapis.com +// title: Google Calendar API +// apis: +// - name: google.calendar.v3.Calendar +// +// visibility: +// rules: +// - selector: "google.calendar.v3.*" +// restriction: PREVIEW +// backend: +// rules: +// - selector: "google.calendar.v3.*" +// address: calendar.example.com +// +// authentication: +// providers: +// - id: google_calendar_auth +// jwks_uri: https://www.googleapis.com/oauth2/v1/certs +// issuer: https://securetoken.google.com +// rules: +// - selector: "*" +// requirements: +// provider_id: google_calendar_auth +message Service { + // The service name, which is a DNS-like logical identifier for the + // service, such as `calendar.googleapis.com`. The service name + // typically goes through DNS verification to make sure the owner + // of the service also owns the DNS name. + string name = 1; + + // The product title for this service, it is the name displayed in Google + // Cloud Console. + string title = 2; + + // The Google project that owns this service. + string producer_project_id = 22; + + // A unique ID for a specific instance of this message, typically assigned + // by the client for tracking purpose. Must be no longer than 63 characters + // and only lower case letters, digits, '.', '_' and '-' are allowed. If + // empty, the server may choose to generate one instead. + string id = 33; + + // A list of API interfaces exported by this service. Only the `name` field + // of the [google.protobuf.Api][google.protobuf.Api] needs to be provided by + // the configuration author, as the remaining fields will be derived from the + // IDL during the normalization process. It is an error to specify an API + // interface here which cannot be resolved against the associated IDL files. + repeated google.protobuf.Api apis = 3; + + // A list of all proto message types included in this API service. + // Types referenced directly or indirectly by the `apis` are automatically + // included. Messages which are not referenced but shall be included, such as + // types used by the `google.protobuf.Any` type, should be listed here by + // name by the configuration author. Example: + // + // types: + // - name: google.protobuf.Int32 + repeated google.protobuf.Type types = 4; + + // A list of all enum types included in this API service. Enums referenced + // directly or indirectly by the `apis` are automatically included. Enums + // which are not referenced but shall be included should be listed here by + // name by the configuration author. Example: + // + // enums: + // - name: google.someapi.v1.SomeEnum + repeated google.protobuf.Enum enums = 5; + + // Additional API documentation. + Documentation documentation = 6; + + // API backend configuration. + Backend backend = 8; + + // HTTP configuration. + Http http = 9; + + // Quota configuration. + Quota quota = 10; + + // Auth configuration. + Authentication authentication = 11; + + // Context configuration. + Context context = 12; + + // Configuration controlling usage of this service. + Usage usage = 15; + + // Configuration for network endpoints. If this is empty, then an endpoint + // with the same name as the service is automatically generated to service all + // defined APIs. + repeated Endpoint endpoints = 18; + + // Configuration for the service control plane. + Control control = 21; + + // Defines the logs used by this service. + repeated LogDescriptor logs = 23; + + // Defines the metrics used by this service. + repeated MetricDescriptor metrics = 24; + + // Defines the monitored resources used by this service. This is required + // by the [Service.monitoring][google.api.Service.monitoring] and + // [Service.logging][google.api.Service.logging] configurations. + repeated MonitoredResourceDescriptor monitored_resources = 25; + + // Billing configuration. + Billing billing = 26; + + // Logging configuration. + Logging logging = 27; + + // Monitoring configuration. + Monitoring monitoring = 28; + + // System parameter configuration. + SystemParameters system_parameters = 29; + + // Output only. The source information for this configuration if available. + SourceInfo source_info = 37; + + // Settings for [Google Cloud Client + // libraries](https://cloud.google.com/apis/docs/cloud-client-libraries) + // generated from APIs defined as protocol buffers. + Publishing publishing = 45; + + // Obsolete. Do not use. + // + // This field has no semantic meaning. The service config compiler always + // sets this field to `3`. + google.protobuf.UInt32Value config_version = 20; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/source_info.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/source_info.proto new file mode 100644 index 00000000..51fe2790 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/source_info.proto @@ -0,0 +1,31 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/any.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "SourceInfoProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Source information used to create a Service Config +message SourceInfo { + // All files used during config generation. + repeated google.protobuf.Any source_files = 1; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/system_parameter.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/system_parameter.proto new file mode 100644 index 00000000..8d29057f --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/system_parameter.proto @@ -0,0 +1,96 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "SystemParameterProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// ### System parameter configuration +// +// A system parameter is a special kind of parameter defined by the API +// system, not by an individual API. It is typically mapped to an HTTP header +// and/or a URL query parameter. This configuration specifies which methods +// change the names of the system parameters. +message SystemParameters { + // Define system parameters. + // + // The parameters defined here will override the default parameters + // implemented by the system. If this field is missing from the service + // config, default system parameters will be used. Default system parameters + // and names is implementation-dependent. + // + // Example: define api key for all methods + // + // system_parameters + // rules: + // - selector: "*" + // parameters: + // - name: api_key + // url_query_parameter: api_key + // + // + // Example: define 2 api key names for a specific method. + // + // system_parameters + // rules: + // - selector: "/ListShelves" + // parameters: + // - name: api_key + // http_header: Api-Key1 + // - name: api_key + // http_header: Api-Key2 + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated SystemParameterRule rules = 1; +} + +// Define a system parameter rule mapping system parameter definitions to +// methods. +message SystemParameterRule { + // Selects the methods to which this rule applies. Use '*' to indicate all + // methods in all APIs. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // Define parameters. Multiple names may be defined for a parameter. + // For a given method call, only one of them should be used. If multiple + // names are used the behavior is implementation-dependent. + // If none of the specified names are present the behavior is + // parameter-dependent. + repeated SystemParameter parameters = 2; +} + +// Define a parameter's name and location. The parameter may be passed as either +// an HTTP header or a URL query parameter, and if both are passed the behavior +// is implementation-dependent. +message SystemParameter { + // Define the name of the parameter, such as "api_key" . It is case sensitive. + string name = 1; + + // Define the HTTP header name to use for the parameter. It is case + // insensitive. + string http_header = 2; + + // Define the URL query parameter name to use for the parameter. It is case + // sensitive. + string url_query_parameter = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/usage.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/usage.proto new file mode 100644 index 00000000..b9384b44 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/usage.proto @@ -0,0 +1,96 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option go_package = "google.golang.org/genproto/googleapis/api/serviceconfig;serviceconfig"; +option java_multiple_files = true; +option java_outer_classname = "UsageProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Configuration controlling usage of a service. +message Usage { + // Requirements that must be satisfied before a consumer project can use the + // service. Each requirement is of the form /; + // for example 'serviceusage.googleapis.com/billing-enabled'. + // + // For Google APIs, a Terms of Service requirement must be included here. + // Google Cloud APIs must include "serviceusage.googleapis.com/tos/cloud". + // Other Google APIs should include + // "serviceusage.googleapis.com/tos/universal". Additional ToS can be + // included based on the business needs. + repeated string requirements = 1; + + // A list of usage rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated UsageRule rules = 6; + + // The full resource name of a channel used for sending notifications to the + // service producer. + // + // Google Service Management currently only supports + // [Google Cloud Pub/Sub](https://cloud.google.com/pubsub) as a notification + // channel. To use Google Cloud Pub/Sub as the channel, this must be the name + // of a Cloud Pub/Sub topic that uses the Cloud Pub/Sub topic name format + // documented in https://cloud.google.com/pubsub/docs/overview. + string producer_notification_channel = 7; +} + +// Usage configuration rules for the service. +// +// NOTE: Under development. +// +// +// Use this rule to configure unregistered calls for the service. Unregistered +// calls are calls that do not contain consumer project identity. +// (Example: calls that do not contain an API key). +// By default, API methods do not allow unregistered calls, and each method call +// must be identified by a consumer project identity. Use this rule to +// allow/disallow unregistered calls. +// +// Example of an API that wants to allow unregistered calls for entire service. +// +// usage: +// rules: +// - selector: "*" +// allow_unregistered_calls: true +// +// Example of a method that wants to allow unregistered calls. +// +// usage: +// rules: +// - selector: "google.example.library.v1.LibraryService.CreateBook" +// allow_unregistered_calls: true +message UsageRule { + // Selects the methods to which this rule applies. Use '*' to indicate all + // methods in all APIs. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // If true, the selected method allows unregistered calls, e.g. calls + // that don't identify any user or application. + bool allow_unregistered_calls = 2; + + // If true, the selected method should skip service control and the control + // plane features, such as quota and billing, will not be available. + // This flag is used by Google Cloud Endpoints to bypass checks for internal + // methods, such as service health check methods. + bool skip_service_control = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/visibility.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/visibility.proto new file mode 100644 index 00000000..8b1f946f --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/api/visibility.proto @@ -0,0 +1,113 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/protobuf/descriptor.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/visibility;visibility"; +option java_multiple_files = true; +option java_outer_classname = "VisibilityProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.EnumOptions { + // See `VisibilityRule`. + google.api.VisibilityRule enum_visibility = 72295727; +} + +extend google.protobuf.EnumValueOptions { + // See `VisibilityRule`. + google.api.VisibilityRule value_visibility = 72295727; +} + +extend google.protobuf.FieldOptions { + // See `VisibilityRule`. + google.api.VisibilityRule field_visibility = 72295727; +} + +extend google.protobuf.MessageOptions { + // See `VisibilityRule`. + google.api.VisibilityRule message_visibility = 72295727; +} + +extend google.protobuf.MethodOptions { + // See `VisibilityRule`. + google.api.VisibilityRule method_visibility = 72295727; +} + +extend google.protobuf.ServiceOptions { + // See `VisibilityRule`. + google.api.VisibilityRule api_visibility = 72295727; +} + +// `Visibility` restricts service consumer's access to service elements, +// such as whether an application can call a visibility-restricted method. +// The restriction is expressed by applying visibility labels on service +// elements. The visibility labels are elsewhere linked to service consumers. +// +// A service can define multiple visibility labels, but a service consumer +// should be granted at most one visibility label. Multiple visibility +// labels for a single service consumer are not supported. +// +// If an element and all its parents have no visibility label, its visibility +// is unconditionally granted. +// +// Example: +// +// visibility: +// rules: +// - selector: google.calendar.Calendar.EnhancedSearch +// restriction: PREVIEW +// - selector: google.calendar.Calendar.Delegate +// restriction: INTERNAL +// +// Here, all methods are publicly visible except for the restricted methods +// EnhancedSearch and Delegate. +message Visibility { + // A list of visibility rules that apply to individual API elements. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated VisibilityRule rules = 1; +} + +// A visibility rule provides visibility configuration for an individual API +// element. +message VisibilityRule { + // Selects methods, messages, fields, enums, etc. to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax + // details. + string selector = 1; + + // A comma-separated list of visibility labels that apply to the `selector`. + // Any of the listed labels can be used to grant the visibility. + // + // If a rule has multiple labels, removing one of the labels but not all of + // them can break clients. + // + // Example: + // + // visibility: + // rules: + // - selector: google.calendar.Calendar.EnhancedSearch + // restriction: INTERNAL, PREVIEW + // + // Removing INTERNAL from this restriction will break clients that rely on + // this method and only had access to it through INTERNAL. + string restriction = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/code.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/code.proto new file mode 100644 index 00000000..7c810af4 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/code.proto @@ -0,0 +1,186 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +option go_package = "google.golang.org/genproto/googleapis/rpc/code;code"; +option java_multiple_files = true; +option java_outer_classname = "CodeProto"; +option java_package = "com.google.rpc"; +option objc_class_prefix = "RPC"; + +// The canonical error codes for gRPC APIs. +// +// +// Sometimes multiple error codes may apply. Services should return +// the most specific error code that applies. For example, prefer +// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply. +// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`. +enum Code { + // Not an error; returned on success. + // + // HTTP Mapping: 200 OK + OK = 0; + + // The operation was cancelled, typically by the caller. + // + // HTTP Mapping: 499 Client Closed Request + CANCELLED = 1; + + // Unknown error. For example, this error may be returned when + // a `Status` value received from another address space belongs to + // an error space that is not known in this address space. Also + // errors raised by APIs that do not return enough error information + // may be converted to this error. + // + // HTTP Mapping: 500 Internal Server Error + UNKNOWN = 2; + + // The client specified an invalid argument. Note that this differs + // from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments + // that are problematic regardless of the state of the system + // (e.g., a malformed file name). + // + // HTTP Mapping: 400 Bad Request + INVALID_ARGUMENT = 3; + + // The deadline expired before the operation could complete. For operations + // that change the state of the system, this error may be returned + // even if the operation has completed successfully. For example, a + // successful response from a server could have been delayed long + // enough for the deadline to expire. + // + // HTTP Mapping: 504 Gateway Timeout + DEADLINE_EXCEEDED = 4; + + // Some requested entity (e.g., file or directory) was not found. + // + // Note to server developers: if a request is denied for an entire class + // of users, such as gradual feature rollout or undocumented allowlist, + // `NOT_FOUND` may be used. If a request is denied for some users within + // a class of users, such as user-based access control, `PERMISSION_DENIED` + // must be used. + // + // HTTP Mapping: 404 Not Found + NOT_FOUND = 5; + + // The entity that a client attempted to create (e.g., file or directory) + // already exists. + // + // HTTP Mapping: 409 Conflict + ALREADY_EXISTS = 6; + + // The caller does not have permission to execute the specified + // operation. `PERMISSION_DENIED` must not be used for rejections + // caused by exhausting some resource (use `RESOURCE_EXHAUSTED` + // instead for those errors). `PERMISSION_DENIED` must not be + // used if the caller can not be identified (use `UNAUTHENTICATED` + // instead for those errors). This error code does not imply the + // request is valid or the requested entity exists or satisfies + // other pre-conditions. + // + // HTTP Mapping: 403 Forbidden + PERMISSION_DENIED = 7; + + // The request does not have valid authentication credentials for the + // operation. + // + // HTTP Mapping: 401 Unauthorized + UNAUTHENTICATED = 16; + + // Some resource has been exhausted, perhaps a per-user quota, or + // perhaps the entire file system is out of space. + // + // HTTP Mapping: 429 Too Many Requests + RESOURCE_EXHAUSTED = 8; + + // The operation was rejected because the system is not in a state + // required for the operation's execution. For example, the directory + // to be deleted is non-empty, an rmdir operation is applied to + // a non-directory, etc. + // + // Service implementors can use the following guidelines to decide + // between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`: + // (a) Use `UNAVAILABLE` if the client can retry just the failing call. + // (b) Use `ABORTED` if the client should retry at a higher level. For + // example, when a client-specified test-and-set fails, indicating the + // client should restart a read-modify-write sequence. + // (c) Use `FAILED_PRECONDITION` if the client should not retry until + // the system state has been explicitly fixed. For example, if an "rmdir" + // fails because the directory is non-empty, `FAILED_PRECONDITION` + // should be returned since the client should not retry unless + // the files are deleted from the directory. + // + // HTTP Mapping: 400 Bad Request + FAILED_PRECONDITION = 9; + + // The operation was aborted, typically due to a concurrency issue such as + // a sequencer check failure or transaction abort. + // + // See the guidelines above for deciding between `FAILED_PRECONDITION`, + // `ABORTED`, and `UNAVAILABLE`. + // + // HTTP Mapping: 409 Conflict + ABORTED = 10; + + // The operation was attempted past the valid range. E.g., seeking or + // reading past end-of-file. + // + // Unlike `INVALID_ARGUMENT`, this error indicates a problem that may + // be fixed if the system state changes. For example, a 32-bit file + // system will generate `INVALID_ARGUMENT` if asked to read at an + // offset that is not in the range [0,2^32-1], but it will generate + // `OUT_OF_RANGE` if asked to read from an offset past the current + // file size. + // + // There is a fair bit of overlap between `FAILED_PRECONDITION` and + // `OUT_OF_RANGE`. We recommend using `OUT_OF_RANGE` (the more specific + // error) when it applies so that callers who are iterating through + // a space can easily look for an `OUT_OF_RANGE` error to detect when + // they are done. + // + // HTTP Mapping: 400 Bad Request + OUT_OF_RANGE = 11; + + // The operation is not implemented or is not supported/enabled in this + // service. + // + // HTTP Mapping: 501 Not Implemented + UNIMPLEMENTED = 12; + + // Internal errors. This means that some invariants expected by the + // underlying system have been broken. This error code is reserved + // for serious errors. + // + // HTTP Mapping: 500 Internal Server Error + INTERNAL = 13; + + // The service is currently unavailable. This is most likely a + // transient condition, which can be corrected by retrying with + // a backoff. Note that it is not always safe to retry + // non-idempotent operations. + // + // See the guidelines above for deciding between `FAILED_PRECONDITION`, + // `ABORTED`, and `UNAVAILABLE`. + // + // HTTP Mapping: 503 Service Unavailable + UNAVAILABLE = 14; + + // Unrecoverable data loss or corruption. + // + // HTTP Mapping: 500 Internal Server Error + DATA_LOSS = 15; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/attribute_context.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/attribute_context.proto new file mode 100644 index 00000000..ef9242e4 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/attribute_context.proto @@ -0,0 +1,344 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc.context; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/rpc/context/attribute_context;attribute_context"; +option java_multiple_files = true; +option java_outer_classname = "AttributeContextProto"; +option java_package = "com.google.rpc.context"; + +// This message defines the standard attribute vocabulary for Google APIs. +// +// An attribute is a piece of metadata that describes an activity on a network +// service. For example, the size of an HTTP request, or the status code of +// an HTTP response. +// +// Each attribute has a type and a name, which is logically defined as +// a proto message field in `AttributeContext`. The field type becomes the +// attribute type, and the field path becomes the attribute name. For example, +// the attribute `source.ip` maps to field `AttributeContext.source.ip`. +// +// This message definition is guaranteed not to have any wire breaking change. +// So you can use it directly for passing attributes across different systems. +// +// NOTE: Different system may generate different subset of attributes. Please +// verify the system specification before relying on an attribute generated +// a system. +message AttributeContext { + // This message defines attributes for a node that handles a network request. + // The node can be either a service or an application that sends, forwards, + // or receives the request. Service peers should fill in + // `principal` and `labels` as appropriate. + message Peer { + // The IP address of the peer. + string ip = 1; + + // The network port of the peer. + int64 port = 2; + + // The labels associated with the peer. + map labels = 6; + + // The identity of this peer. Similar to `Request.auth.principal`, but + // relative to the peer instead of the request. For example, the + // identity associated with a load balancer that forwarded the request. + string principal = 7; + + // The CLDR country/region code associated with the above IP address. + // If the IP address is private, the `region_code` should reflect the + // physical location where this peer is running. + string region_code = 8; + } + + // This message defines attributes associated with API operations, such as + // a network API request. The terminology is based on the conventions used + // by Google APIs, Istio, and OpenAPI. + message Api { + // The API service name. It is a logical identifier for a networked API, + // such as "pubsub.googleapis.com". The naming syntax depends on the + // API management system being used for handling the request. + string service = 1; + + // The API operation name. For gRPC requests, it is the fully qualified API + // method name, such as "google.pubsub.v1.Publisher.Publish". For OpenAPI + // requests, it is the `operationId`, such as "getPet". + string operation = 2; + + // The API protocol used for sending the request, such as "http", "https", + // "grpc", or "internal". + string protocol = 3; + + // The API version associated with the API operation above, such as "v1" or + // "v1alpha1". + string version = 4; + } + + // This message defines request authentication attributes. Terminology is + // based on the JSON Web Token (JWT) standard, but the terms also + // correlate to concepts in other standards. + message Auth { + // The authenticated principal. Reflects the issuer (`iss`) and subject + // (`sub`) claims within a JWT. The issuer and subject should be `/` + // delimited, with `/` percent-encoded within the subject fragment. For + // Google accounts, the principal format is: + // "https://accounts.google.com/{id}" + string principal = 1; + + // The intended audience(s) for this authentication information. Reflects + // the audience (`aud`) claim within a JWT. The audience + // value(s) depends on the `issuer`, but typically include one or more of + // the following pieces of information: + // + // * The services intended to receive the credential. For example, + // ["https://pubsub.googleapis.com/", "https://storage.googleapis.com/"]. + // * A set of service-based scopes. For example, + // ["https://www.googleapis.com/auth/cloud-platform"]. + // * The client id of an app, such as the Firebase project id for JWTs + // from Firebase Auth. + // + // Consult the documentation for the credential issuer to determine the + // information provided. + repeated string audiences = 2; + + // The authorized presenter of the credential. Reflects the optional + // Authorized Presenter (`azp`) claim within a JWT or the + // OAuth client id. For example, a Google Cloud Platform client id looks + // as follows: "123456789012.apps.googleusercontent.com". + string presenter = 3; + + // Structured claims presented with the credential. JWTs include + // `{key: value}` pairs for standard and private claims. The following + // is a subset of the standard required and optional claims that would + // typically be presented for a Google-based JWT: + // + // {'iss': 'accounts.google.com', + // 'sub': '113289723416554971153', + // 'aud': ['123456789012', 'pubsub.googleapis.com'], + // 'azp': '123456789012.apps.googleusercontent.com', + // 'email': 'jsmith@example.com', + // 'iat': 1353601026, + // 'exp': 1353604926} + // + // SAML assertions are similarly specified, but with an identity provider + // dependent structure. + google.protobuf.Struct claims = 4; + + // A list of access level resource names that allow resources to be + // accessed by authenticated requester. It is part of Secure GCP processing + // for the incoming request. An access level string has the format: + // "//{api_service_name}/accessPolicies/{policy_id}/accessLevels/{short_name}" + // + // Example: + // "//accesscontextmanager.googleapis.com/accessPolicies/MY_POLICY_ID/accessLevels/MY_LEVEL" + repeated string access_levels = 5; + } + + // This message defines attributes for an HTTP request. If the actual + // request is not an HTTP request, the runtime system should try to map + // the actual request to an equivalent HTTP request. + message Request { + // The unique ID for a request, which can be propagated to downstream + // systems. The ID should have low probability of collision + // within a single day for a specific service. + string id = 1; + + // The HTTP request method, such as `GET`, `POST`. + string method = 2; + + // The HTTP request headers. If multiple headers share the same key, they + // must be merged according to the HTTP spec. All header keys must be + // lowercased, because HTTP header keys are case-insensitive. + map headers = 3; + + // The HTTP URL path, excluding the query parameters. + string path = 4; + + // The HTTP request `Host` header value. + string host = 5; + + // The HTTP URL scheme, such as `http` and `https`. + string scheme = 6; + + // The HTTP URL query in the format of `name1=value1&name2=value2`, as it + // appears in the first line of the HTTP request. No decoding is performed. + string query = 7; + + // The timestamp when the `destination` service receives the last byte of + // the request. + google.protobuf.Timestamp time = 9; + + // The HTTP request size in bytes. If unknown, it must be -1. + int64 size = 10; + + // The network protocol used with the request, such as "http/1.1", + // "spdy/3", "h2", "h2c", "webrtc", "tcp", "udp", "quic". See + // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids + // for details. + string protocol = 11; + + // A special parameter for request reason. It is used by security systems + // to associate auditing information with a request. + string reason = 12; + + // The request authentication. May be absent for unauthenticated requests. + // Derived from the HTTP request `Authorization` header or equivalent. + Auth auth = 13; + } + + // This message defines attributes for a typical network response. It + // generally models semantics of an HTTP response. + message Response { + // The HTTP response status code, such as `200` and `404`. + int64 code = 1; + + // The HTTP response size in bytes. If unknown, it must be -1. + int64 size = 2; + + // The HTTP response headers. If multiple headers share the same key, they + // must be merged according to HTTP spec. All header keys must be + // lowercased, because HTTP header keys are case-insensitive. + map headers = 3; + + // The timestamp when the `destination` service sends the last byte of + // the response. + google.protobuf.Timestamp time = 4; + + // The amount of time it takes the backend service to fully respond to a + // request. Measured from when the destination service starts to send the + // request to the backend until when the destination service receives the + // complete response from the backend. + google.protobuf.Duration backend_latency = 5; + } + + // This message defines core attributes for a resource. A resource is an + // addressable (named) entity provided by the destination service. For + // example, a file stored on a network storage service. + message Resource { + // The name of the service that this resource belongs to, such as + // `pubsub.googleapis.com`. The service may be different from the DNS + // hostname that actually serves the request. + string service = 1; + + // The stable identifier (name) of a resource on the `service`. A resource + // can be logically identified as "//{resource.service}/{resource.name}". + // The differences between a resource name and a URI are: + // + // * Resource name is a logical identifier, independent of network + // protocol and API version. For example, + // `//pubsub.googleapis.com/projects/123/topics/news-feed`. + // * URI often includes protocol and version information, so it can + // be used directly by applications. For example, + // `https://pubsub.googleapis.com/v1/projects/123/topics/news-feed`. + // + // See https://cloud.google.com/apis/design/resource_names for details. + string name = 2; + + // The type of the resource. The syntax is platform-specific because + // different platforms define their resources differently. + // + // For Google APIs, the type format must be "{service}/{kind}", such as + // "pubsub.googleapis.com/Topic". + string type = 3; + + // The labels or tags on the resource, such as AWS resource tags and + // Kubernetes resource labels. + map labels = 4; + + // The unique identifier of the resource. UID is unique in the time + // and space for this resource within the scope of the service. It is + // typically generated by the server on successful creation of a resource + // and must not be changed. UID is used to uniquely identify resources + // with resource name reuses. This should be a UUID4. + string uid = 5; + + // Annotations is an unstructured key-value map stored with a resource that + // may be set by external tools to store and retrieve arbitrary metadata. + // They are not queryable and should be preserved when modifying objects. + // + // More info: https://kubernetes.io/docs/user-guide/annotations + map annotations = 6; + + // Mutable. The display name set by clients. Must be <= 63 characters. + string display_name = 7; + + // Output only. The timestamp when the resource was created. This may + // be either the time creation was initiated or when it was completed. + google.protobuf.Timestamp create_time = 8; + + // Output only. The timestamp when the resource was last updated. Any + // change to the resource made by users must refresh this value. + // Changes to a resource made by the service should refresh this value. + google.protobuf.Timestamp update_time = 9; + + // Output only. The timestamp when the resource was deleted. + // If the resource is not deleted, this must be empty. + google.protobuf.Timestamp delete_time = 10; + + // Output only. An opaque value that uniquely identifies a version or + // generation of a resource. It can be used to confirm that the client + // and server agree on the ordering of a resource being written. + string etag = 11; + + // Immutable. The location of the resource. The location encoding is + // specific to the service provider, and new encoding may be introduced + // as the service evolves. + // + // For Google Cloud products, the encoding is what is used by Google Cloud + // APIs, such as `us-east1`, `aws-us-east-1`, and `azure-eastus2`. The + // semantics of `location` is identical to the + // `cloud.googleapis.com/location` label used by some Google Cloud APIs. + string location = 12; + } + + // The origin of a network activity. In a multi hop network activity, + // the origin represents the sender of the first hop. For the first hop, + // the `source` and the `origin` must have the same content. + Peer origin = 7; + + // The source of a network activity, such as starting a TCP connection. + // In a multi hop network activity, the source represents the sender of the + // last hop. + Peer source = 1; + + // The destination of a network activity, such as accepting a TCP connection. + // In a multi hop network activity, the destination represents the receiver of + // the last hop. + Peer destination = 2; + + // Represents a network request, such as an HTTP request. + Request request = 3; + + // Represents a network response, such as an HTTP response. + Response response = 4; + + // Represents a target resource that is involved with a network activity. + // If multiple resources are involved with an activity, this must be the + // primary one. + Resource resource = 5; + + // Represents an API operation that is involved to a network activity. + Api api = 6; + + // Supports extensions for advanced use cases, such as logs and metrics. + repeated google.protobuf.Any extensions = 8; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/audit_context.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/audit_context.proto new file mode 100644 index 00000000..7b8b7051 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/context/audit_context.proto @@ -0,0 +1,49 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc.context; + +import "google/protobuf/struct.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/rpc/context;context"; +option java_multiple_files = true; +option java_outer_classname = "AuditContextProto"; +option java_package = "com.google.rpc.context"; + +// `AuditContext` provides information that is needed for audit logging. +message AuditContext { + // Serialized audit log. + bytes audit_log = 1; + + // An API request message that is scrubbed based on the method annotation. + // This field should only be filled if audit_log field is present. + // Service Control will use this to assemble a complete log for Cloud Audit + // Logs and Google internal audit logs. + google.protobuf.Struct scrubbed_request = 2; + + // An API response message that is scrubbed based on the method annotation. + // This field should only be filled if audit_log field is present. + // Service Control will use this to assemble a complete log for Cloud Audit + // Logs and Google internal audit logs. + google.protobuf.Struct scrubbed_response = 3; + + // Number of scrubbed response items. + int32 scrubbed_response_item_count = 4; + + // Audit resource name which is scrubbed. + string target_resource = 5; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/error_details.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/error_details.proto new file mode 100644 index 00000000..c489e831 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/error_details.proto @@ -0,0 +1,285 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +import "google/protobuf/duration.proto"; + +option go_package = "google.golang.org/genproto/googleapis/rpc/errdetails;errdetails"; +option java_multiple_files = true; +option java_outer_classname = "ErrorDetailsProto"; +option java_package = "com.google.rpc"; +option objc_class_prefix = "RPC"; + +// Describes the cause of the error with structured details. +// +// Example of an error when contacting the "pubsub.googleapis.com" API when it +// is not enabled: +// +// { "reason": "API_DISABLED" +// "domain": "googleapis.com" +// "metadata": { +// "resource": "projects/123", +// "service": "pubsub.googleapis.com" +// } +// } +// +// This response indicates that the pubsub.googleapis.com API is not enabled. +// +// Example of an error that is returned when attempting to create a Spanner +// instance in a region that is out of stock: +// +// { "reason": "STOCKOUT" +// "domain": "spanner.googleapis.com", +// "metadata": { +// "availableRegions": "us-central1,us-east2" +// } +// } +message ErrorInfo { + // The reason of the error. This is a constant value that identifies the + // proximate cause of the error. Error reasons are unique within a particular + // domain of errors. This should be at most 63 characters and match a + // regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`, which represents + // UPPER_SNAKE_CASE. + string reason = 1; + + // The logical grouping to which the "reason" belongs. The error domain + // is typically the registered service name of the tool or product that + // generates the error. Example: "pubsub.googleapis.com". If the error is + // generated by some common infrastructure, the error domain must be a + // globally unique value that identifies the infrastructure. For Google API + // infrastructure, the error domain is "googleapis.com". + string domain = 2; + + // Additional structured details about this error. + // + // Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in + // length. When identifying the current value of an exceeded limit, the units + // should be contained in the key, not the value. For example, rather than + // {"instanceLimit": "100/request"}, should be returned as, + // {"instanceLimitPerRequest": "100"}, if the client exceeds the number of + // instances that can be created in a single (batch) request. + map metadata = 3; +} + +// Describes when the clients can retry a failed request. Clients could ignore +// the recommendation here or retry when this information is missing from error +// responses. +// +// It's always recommended that clients should use exponential backoff when +// retrying. +// +// Clients should wait until `retry_delay` amount of time has passed since +// receiving the error response before retrying. If retrying requests also +// fail, clients should use an exponential backoff scheme to gradually increase +// the delay between retries based on `retry_delay`, until either a maximum +// number of retries have been reached or a maximum retry delay cap has been +// reached. +message RetryInfo { + // Clients should wait at least this long between retrying the same request. + google.protobuf.Duration retry_delay = 1; +} + +// Describes additional debugging info. +message DebugInfo { + // The stack trace entries indicating where the error occurred. + repeated string stack_entries = 1; + + // Additional debugging information provided by the server. + string detail = 2; +} + +// Describes how a quota check failed. +// +// For example if a daily limit was exceeded for the calling project, +// a service could respond with a QuotaFailure detail containing the project +// id and the description of the quota limit that was exceeded. If the +// calling project hasn't enabled the service in the developer console, then +// a service could respond with the project id and set `service_disabled` +// to true. +// +// Also see RetryInfo and Help types for other details about handling a +// quota failure. +message QuotaFailure { + // A message type used to describe a single quota violation. For example, a + // daily quota or a custom quota that was exceeded. + message Violation { + // The subject on which the quota check failed. + // For example, "clientip:" or "project:". + string subject = 1; + + // A description of how the quota check failed. Clients can use this + // description to find more about the quota configuration in the service's + // public documentation, or find the relevant quota limit to adjust through + // developer console. + // + // For example: "Service disabled" or "Daily Limit for read operations + // exceeded". + string description = 2; + } + + // Describes all quota violations. + repeated Violation violations = 1; +} + +// Describes what preconditions have failed. +// +// For example, if an RPC failed because it required the Terms of Service to be +// acknowledged, it could list the terms of service violation in the +// PreconditionFailure message. +message PreconditionFailure { + // A message type used to describe a single precondition failure. + message Violation { + // The type of PreconditionFailure. We recommend using a service-specific + // enum type to define the supported precondition violation subjects. For + // example, "TOS" for "Terms of Service violation". + string type = 1; + + // The subject, relative to the type, that failed. + // For example, "google.com/cloud" relative to the "TOS" type would indicate + // which terms of service is being referenced. + string subject = 2; + + // A description of how the precondition failed. Developers can use this + // description to understand how to fix the failure. + // + // For example: "Terms of service not accepted". + string description = 3; + } + + // Describes all precondition violations. + repeated Violation violations = 1; +} + +// Describes violations in a client request. This error type focuses on the +// syntactic aspects of the request. +message BadRequest { + // A message type used to describe a single bad request field. + message FieldViolation { + // A path that leads to a field in the request body. The value will be a + // sequence of dot-separated identifiers that identify a protocol buffer + // field. + // + // Consider the following: + // + // message CreateContactRequest { + // message EmailAddress { + // enum Type { + // TYPE_UNSPECIFIED = 0; + // HOME = 1; + // WORK = 2; + // } + // + // optional string email = 1; + // repeated EmailType type = 2; + // } + // + // string full_name = 1; + // repeated EmailAddress email_addresses = 2; + // } + // + // In this example, in proto `field` could take one of the following values: + // + // * `full_name` for a violation in the `full_name` value + // * `email_addresses[1].email` for a violation in the `email` field of the + // first `email_addresses` message + // * `email_addresses[3].type[2]` for a violation in the second `type` + // value in the third `email_addresses` message. + // + // In JSON, the same values are represented as: + // + // * `fullName` for a violation in the `fullName` value + // * `emailAddresses[1].email` for a violation in the `email` field of the + // first `emailAddresses` message + // * `emailAddresses[3].type[2]` for a violation in the second `type` + // value in the third `emailAddresses` message. + string field = 1; + + // A description of why the request element is bad. + string description = 2; + } + + // Describes all violations in a client request. + repeated FieldViolation field_violations = 1; +} + +// Contains metadata about the request that clients can attach when filing a bug +// or providing other forms of feedback. +message RequestInfo { + // An opaque string that should only be interpreted by the service generating + // it. For example, it can be used to identify requests in the service's logs. + string request_id = 1; + + // Any data that was used to serve this request. For example, an encrypted + // stack trace that can be sent back to the service provider for debugging. + string serving_data = 2; +} + +// Describes the resource that is being accessed. +message ResourceInfo { + // A name for the type of resource being accessed, e.g. "sql table", + // "cloud storage bucket", "file", "Google calendar"; or the type URL + // of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic". + string resource_type = 1; + + // The name of the resource being accessed. For example, a shared calendar + // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current + // error is + // [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED]. + string resource_name = 2; + + // The owner of the resource (optional). + // For example, "user:" or "project:". + string owner = 3; + + // Describes what error is encountered when accessing this resource. + // For example, updating a cloud project may require the `writer` permission + // on the developer console project. + string description = 4; +} + +// Provides links to documentation or for performing an out of band action. +// +// For example, if a quota check failed with an error indicating the calling +// project hasn't enabled the accessed service, this can contain a URL pointing +// directly to the right place in the developer console to flip the bit. +message Help { + // Describes a URL link. + message Link { + // Describes what the link offers. + string description = 1; + + // The URL of the link. + string url = 2; + } + + // URL(s) pointing to additional information on handling the current error. + repeated Link links = 1; +} + +// Provides a localized error message that is safe to return to the user +// which can be attached to an RPC error. +message LocalizedMessage { + // The locale used following the specification defined at + // https://www.rfc-editor.org/rfc/bcp/bcp47.txt. + // Examples are: "en-US", "fr-CH", "es-MX" + string locale = 1; + + // The localized error message in the above locale. + string message = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/http.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/http.proto new file mode 100644 index 00000000..299a71fd --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/http.proto @@ -0,0 +1,64 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +option go_package = "google.golang.org/genproto/googleapis/rpc/http;http"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.rpc"; +option objc_class_prefix = "RPC"; + +// Represents an HTTP request. +message HttpRequest { + // The HTTP request method. + string method = 1; + + // The HTTP request URI. + string uri = 2; + + // The HTTP request headers. The ordering of the headers is significant. + // Multiple headers with the same key may present for the request. + repeated HttpHeader headers = 3; + + // The HTTP request body. If the body is not expected, it should be empty. + bytes body = 4; +} + +// Represents an HTTP response. +message HttpResponse { + // The HTTP status code, such as 200 or 404. + int32 status = 1; + + // The HTTP reason phrase, such as "OK" or "Not Found". + string reason = 2; + + // The HTTP response headers. The ordering of the headers is significant. + // Multiple headers with the same key may present for the response. + repeated HttpHeader headers = 3; + + // The HTTP response body. If the body is not expected, it should be empty. + bytes body = 4; +} + +// Represents an HTTP header. +message HttpHeader { + // The HTTP header key. It is case insensitive. + string key = 1; + + // The HTTP header value. + string value = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/status.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/status.proto new file mode 100644 index 00000000..923e1693 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/rpc/status.proto @@ -0,0 +1,49 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +import "google/protobuf/any.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/rpc/status;status"; +option java_multiple_files = true; +option java_outer_classname = "StatusProto"; +option java_package = "com.google.rpc"; +option objc_class_prefix = "RPC"; + +// The `Status` type defines a logical error model that is suitable for +// different programming environments, including REST APIs and RPC APIs. It is +// used by [gRPC](https://github.com/grpc). Each `Status` message contains +// three pieces of data: error code, error message, and error details. +// +// You can find out more about this error model and how to work with it in the +// [API Design Guide](https://cloud.google.com/apis/design/errors). +message Status { + // The status code, which should be an enum value of + // [google.rpc.Code][google.rpc.Code]. + int32 code = 1; + + // A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the + // [google.rpc.Status.details][google.rpc.Status.details] field, or localized + // by the client. + string message = 2; + + // A list of messages that carry the error details. There is a common set of + // message types for APIs to use. + repeated google.protobuf.Any details = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/calendar_period.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/calendar_period.proto new file mode 100644 index 00000000..82f5690b --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/calendar_period.proto @@ -0,0 +1,56 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option go_package = "google.golang.org/genproto/googleapis/type/calendarperiod;calendarperiod"; +option java_multiple_files = true; +option java_outer_classname = "CalendarPeriodProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// A `CalendarPeriod` represents the abstract concept of a time period that has +// a canonical start. Grammatically, "the start of the current +// `CalendarPeriod`." All calendar times begin at midnight UTC. +enum CalendarPeriod { + // Undefined period, raises an error. + CALENDAR_PERIOD_UNSPECIFIED = 0; + + // A day. + DAY = 1; + + // A week. Weeks begin on Monday, following + // [ISO 8601](https://en.wikipedia.org/wiki/ISO_week_date). + WEEK = 2; + + // A fortnight. The first calendar fortnight of the year begins at the start + // of week 1 according to + // [ISO 8601](https://en.wikipedia.org/wiki/ISO_week_date). + FORTNIGHT = 3; + + // A month. + MONTH = 4; + + // A quarter. Quarters start on dates 1-Jan, 1-Apr, 1-Jul, and 1-Oct of each + // year. + QUARTER = 5; + + // A half-year. Half-years start on dates 1-Jan and 1-Jul. + HALF = 6; + + // A year. + YEAR = 7; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/color.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/color.proto new file mode 100644 index 00000000..5dc85a6a --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/color.proto @@ -0,0 +1,174 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +import "google/protobuf/wrappers.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/color;color"; +option java_multiple_files = true; +option java_outer_classname = "ColorProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a color in the RGBA color space. This representation is designed +// for simplicity of conversion to/from color representations in various +// languages over compactness. For example, the fields of this representation +// can be trivially provided to the constructor of `java.awt.Color` in Java; it +// can also be trivially provided to UIColor's `+colorWithRed:green:blue:alpha` +// method in iOS; and, with just a little work, it can be easily formatted into +// a CSS `rgba()` string in JavaScript. +// +// This reference page doesn't carry information about the absolute color +// space +// that should be used to interpret the RGB value (e.g. sRGB, Adobe RGB, +// DCI-P3, BT.2020, etc.). By default, applications should assume the sRGB color +// space. +// +// When color equality needs to be decided, implementations, unless +// documented otherwise, treat two colors as equal if all their red, +// green, blue, and alpha values each differ by at most 1e-5. +// +// Example (Java): +// +// import com.google.type.Color; +// +// // ... +// public static java.awt.Color fromProto(Color protocolor) { +// float alpha = protocolor.hasAlpha() +// ? protocolor.getAlpha().getValue() +// : 1.0; +// +// return new java.awt.Color( +// protocolor.getRed(), +// protocolor.getGreen(), +// protocolor.getBlue(), +// alpha); +// } +// +// public static Color toProto(java.awt.Color color) { +// float red = (float) color.getRed(); +// float green = (float) color.getGreen(); +// float blue = (float) color.getBlue(); +// float denominator = 255.0; +// Color.Builder resultBuilder = +// Color +// .newBuilder() +// .setRed(red / denominator) +// .setGreen(green / denominator) +// .setBlue(blue / denominator); +// int alpha = color.getAlpha(); +// if (alpha != 255) { +// result.setAlpha( +// FloatValue +// .newBuilder() +// .setValue(((float) alpha) / denominator) +// .build()); +// } +// return resultBuilder.build(); +// } +// // ... +// +// Example (iOS / Obj-C): +// +// // ... +// static UIColor* fromProto(Color* protocolor) { +// float red = [protocolor red]; +// float green = [protocolor green]; +// float blue = [protocolor blue]; +// FloatValue* alpha_wrapper = [protocolor alpha]; +// float alpha = 1.0; +// if (alpha_wrapper != nil) { +// alpha = [alpha_wrapper value]; +// } +// return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; +// } +// +// static Color* toProto(UIColor* color) { +// CGFloat red, green, blue, alpha; +// if (![color getRed:&red green:&green blue:&blue alpha:&alpha]) { +// return nil; +// } +// Color* result = [[Color alloc] init]; +// [result setRed:red]; +// [result setGreen:green]; +// [result setBlue:blue]; +// if (alpha <= 0.9999) { +// [result setAlpha:floatWrapperWithValue(alpha)]; +// } +// [result autorelease]; +// return result; +// } +// // ... +// +// Example (JavaScript): +// +// // ... +// +// var protoToCssColor = function(rgb_color) { +// var redFrac = rgb_color.red || 0.0; +// var greenFrac = rgb_color.green || 0.0; +// var blueFrac = rgb_color.blue || 0.0; +// var red = Math.floor(redFrac * 255); +// var green = Math.floor(greenFrac * 255); +// var blue = Math.floor(blueFrac * 255); +// +// if (!('alpha' in rgb_color)) { +// return rgbToCssColor(red, green, blue); +// } +// +// var alphaFrac = rgb_color.alpha.value || 0.0; +// var rgbParams = [red, green, blue].join(','); +// return ['rgba(', rgbParams, ',', alphaFrac, ')'].join(''); +// }; +// +// var rgbToCssColor = function(red, green, blue) { +// var rgbNumber = new Number((red << 16) | (green << 8) | blue); +// var hexString = rgbNumber.toString(16); +// var missingZeros = 6 - hexString.length; +// var resultBuilder = ['#']; +// for (var i = 0; i < missingZeros; i++) { +// resultBuilder.push('0'); +// } +// resultBuilder.push(hexString); +// return resultBuilder.join(''); +// }; +// +// // ... +message Color { + // The amount of red in the color as a value in the interval [0, 1]. + float red = 1; + + // The amount of green in the color as a value in the interval [0, 1]. + float green = 2; + + // The amount of blue in the color as a value in the interval [0, 1]. + float blue = 3; + + // The fraction of this color that should be applied to the pixel. That is, + // the final pixel color is defined by the equation: + // + // `pixel color = alpha * (this color) + (1.0 - alpha) * (background color)` + // + // This means that a value of 1.0 corresponds to a solid color, whereas + // a value of 0.0 corresponds to a completely transparent color. This + // uses a wrapper message rather than a simple float scalar so that it is + // possible to distinguish between a default value and the value being unset. + // If omitted, this color object is rendered as a solid color + // (as if the alpha value had been explicitly given a value of 1.0). + google.protobuf.FloatValue alpha = 4; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/date.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/date.proto new file mode 100644 index 00000000..e4e730e6 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/date.proto @@ -0,0 +1,52 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/date;date"; +option java_multiple_files = true; +option java_outer_classname = "DateProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a whole or partial calendar date, such as a birthday. The time of +// day and time zone are either specified elsewhere or are insignificant. The +// date is relative to the Gregorian Calendar. This can represent one of the +// following: +// +// * A full date, with non-zero year, month, and day values +// * A month and day value, with a zero year, such as an anniversary +// * A year on its own, with zero month and day values +// * A year and month value, with a zero day, such as a credit card expiration +// date +// +// Related types are [google.type.TimeOfDay][google.type.TimeOfDay] and +// `google.protobuf.Timestamp`. +message Date { + // Year of the date. Must be from 1 to 9999, or 0 to specify a date without + // a year. + int32 year = 1; + + // Month of a year. Must be from 1 to 12, or 0 to specify a year without a + // month and day. + int32 month = 2; + + // Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 + // to specify a year by itself or a year and month where the day isn't + // significant. + int32 day = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/datetime.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/datetime.proto new file mode 100644 index 00000000..cfed85d7 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/datetime.proto @@ -0,0 +1,104 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +import "google/protobuf/duration.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/datetime;datetime"; +option java_multiple_files = true; +option java_outer_classname = "DateTimeProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents civil time (or occasionally physical time). +// +// This type can represent a civil time in one of a few possible ways: +// +// * When utc_offset is set and time_zone is unset: a civil time on a calendar +// day with a particular offset from UTC. +// * When time_zone is set and utc_offset is unset: a civil time on a calendar +// day in a particular time zone. +// * When neither time_zone nor utc_offset is set: a civil time on a calendar +// day in local time. +// +// The date is relative to the Proleptic Gregorian Calendar. +// +// If year is 0, the DateTime is considered not to have a specific year. month +// and day must have valid, non-zero values. +// +// This type may also be used to represent a physical time if all the date and +// time fields are set and either case of the `time_offset` oneof is set. +// Consider using `Timestamp` message for physical time instead. If your use +// case also would like to store the user's timezone, that can be done in +// another field. +// +// This type is more flexible than some applications may want. Make sure to +// document and validate your application's limitations. +message DateTime { + // Optional. Year of date. Must be from 1 to 9999, or 0 if specifying a + // datetime without a year. + int32 year = 1; + + // Required. Month of year. Must be from 1 to 12. + int32 month = 2; + + // Required. Day of month. Must be from 1 to 31 and valid for the year and + // month. + int32 day = 3; + + // Required. Hours of day in 24 hour format. Should be from 0 to 23. An API + // may choose to allow the value "24:00:00" for scenarios like business + // closing time. + int32 hours = 4; + + // Required. Minutes of hour of day. Must be from 0 to 59. + int32 minutes = 5; + + // Required. Seconds of minutes of the time. Must normally be from 0 to 59. An + // API may allow the value 60 if it allows leap-seconds. + int32 seconds = 6; + + // Required. Fractions of seconds in nanoseconds. Must be from 0 to + // 999,999,999. + int32 nanos = 7; + + // Optional. Specifies either the UTC offset or the time zone of the DateTime. + // Choose carefully between them, considering that time zone data may change + // in the future (for example, a country modifies their DST start/end dates, + // and future DateTimes in the affected range had already been stored). + // If omitted, the DateTime is considered to be in local time. + oneof time_offset { + // UTC offset. Must be whole seconds, between -18 hours and +18 hours. + // For example, a UTC offset of -4:00 would be represented as + // { seconds: -14400 }. + google.protobuf.Duration utc_offset = 8; + + // Time zone. + TimeZone time_zone = 9; + } +} + +// Represents a time zone from the +// [IANA Time Zone Database](https://www.iana.org/time-zones). +message TimeZone { + // IANA Time Zone Database time zone, e.g. "America/New_York". + string id = 1; + + // Optional. IANA Time Zone Database version number, e.g. "2019a". + string version = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/dayofweek.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/dayofweek.proto new file mode 100644 index 00000000..4c80c62e --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/dayofweek.proto @@ -0,0 +1,50 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option go_package = "google.golang.org/genproto/googleapis/type/dayofweek;dayofweek"; +option java_multiple_files = true; +option java_outer_classname = "DayOfWeekProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a day of the week. +enum DayOfWeek { + // The day of the week is unspecified. + DAY_OF_WEEK_UNSPECIFIED = 0; + + // Monday + MONDAY = 1; + + // Tuesday + TUESDAY = 2; + + // Wednesday + WEDNESDAY = 3; + + // Thursday + THURSDAY = 4; + + // Friday + FRIDAY = 5; + + // Saturday + SATURDAY = 6; + + // Sunday + SUNDAY = 7; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/decimal.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/decimal.proto new file mode 100644 index 00000000..beb18a5d --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/decimal.proto @@ -0,0 +1,95 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/decimal;decimal"; +option java_multiple_files = true; +option java_outer_classname = "DecimalProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// A representation of a decimal value, such as 2.5. Clients may convert values +// into language-native decimal formats, such as Java's [BigDecimal][] or +// Python's [decimal.Decimal][]. +// +// [BigDecimal]: +// https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigDecimal.html +// [decimal.Decimal]: https://docs.python.org/3/library/decimal.html +message Decimal { + // The decimal value, as a string. + // + // The string representation consists of an optional sign, `+` (`U+002B`) + // or `-` (`U+002D`), followed by a sequence of zero or more decimal digits + // ("the integer"), optionally followed by a fraction, optionally followed + // by an exponent. + // + // The fraction consists of a decimal point followed by zero or more decimal + // digits. The string must contain at least one digit in either the integer + // or the fraction. The number formed by the sign, the integer and the + // fraction is referred to as the significand. + // + // The exponent consists of the character `e` (`U+0065`) or `E` (`U+0045`) + // followed by one or more decimal digits. + // + // Services **should** normalize decimal values before storing them by: + // + // - Removing an explicitly-provided `+` sign (`+2.5` -> `2.5`). + // - Replacing a zero-length integer value with `0` (`.5` -> `0.5`). + // - Coercing the exponent character to lower-case (`2.5E8` -> `2.5e8`). + // - Removing an explicitly-provided zero exponent (`2.5e0` -> `2.5`). + // + // Services **may** perform additional normalization based on its own needs + // and the internal decimal implementation selected, such as shifting the + // decimal point and exponent value together (example: `2.5e-1` <-> `0.25`). + // Additionally, services **may** preserve trailing zeroes in the fraction + // to indicate increased precision, but are not required to do so. + // + // Note that only the `.` character is supported to divide the integer + // and the fraction; `,` **should not** be supported regardless of locale. + // Additionally, thousand separators **should not** be supported. If a + // service does support them, values **must** be normalized. + // + // The ENBF grammar is: + // + // DecimalString = + // [Sign] Significand [Exponent]; + // + // Sign = '+' | '-'; + // + // Significand = + // Digits ['.'] [Digits] | [Digits] '.' Digits; + // + // Exponent = ('e' | 'E') [Sign] Digits; + // + // Digits = { '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' }; + // + // Services **should** clearly document the range of supported values, the + // maximum supported precision (total number of digits), and, if applicable, + // the scale (number of digits after the decimal point), as well as how it + // behaves when receiving out-of-bounds values. + // + // Services **may** choose to accept values passed as input even when the + // value has a higher precision or scale than the service supports, and + // **should** round the value to fit the supported scale. Alternatively, the + // service **may** error with `400 Bad Request` (`INVALID_ARGUMENT` in gRPC) + // if precision would be lost. + // + // Services **should** error with `400 Bad Request` (`INVALID_ARGUMENT` in + // gRPC) if the service receives a value outside of the supported range. + string value = 1; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/expr.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/expr.proto new file mode 100644 index 00000000..af0778cf --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/expr.proto @@ -0,0 +1,73 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option go_package = "google.golang.org/genproto/googleapis/type/expr;expr"; +option java_multiple_files = true; +option java_outer_classname = "ExprProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a textual expression in the Common Expression Language (CEL) +// syntax. CEL is a C-like expression language. The syntax and semantics of CEL +// are documented at https://github.com/google/cel-spec. +// +// Example (Comparison): +// +// title: "Summary size limit" +// description: "Determines if a summary is less than 100 chars" +// expression: "document.summary.size() < 100" +// +// Example (Equality): +// +// title: "Requestor is owner" +// description: "Determines if requestor is the document owner" +// expression: "document.owner == request.auth.claims.email" +// +// Example (Logic): +// +// title: "Public documents" +// description: "Determine whether the document should be publicly visible" +// expression: "document.type != 'private' && document.type != 'internal'" +// +// Example (Data Manipulation): +// +// title: "Notification string" +// description: "Create a notification string with a timestamp." +// expression: "'New message received at ' + string(document.create_time)" +// +// The exact variables and functions that may be referenced within an expression +// are determined by the service that evaluates it. See the service +// documentation for additional information. +message Expr { + // Textual representation of an expression in Common Expression Language + // syntax. + string expression = 1; + + // Optional. Title for the expression, i.e. a short string describing + // its purpose. This can be used e.g. in UIs which allow to enter the + // expression. + string title = 2; + + // Optional. Description of the expression. This is a longer text which + // describes the expression, e.g. when hovered over it in a UI. + string description = 3; + + // Optional. String indicating the location of the expression for error + // reporting, e.g. a file name and a position in the file. + string location = 4; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/fraction.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/fraction.proto new file mode 100644 index 00000000..6c5ae6e2 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/fraction.proto @@ -0,0 +1,33 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option go_package = "google.golang.org/genproto/googleapis/type/fraction;fraction"; +option java_multiple_files = true; +option java_outer_classname = "FractionProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a fraction in terms of a numerator divided by a denominator. +message Fraction { + // The numerator in the fraction, e.g. 2 in 2/3. + int64 numerator = 1; + + // The value by which the numerator is divided, e.g. 3 in 2/3. Must be + // positive. + int64 denominator = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/interval.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/interval.proto new file mode 100644 index 00000000..9702324c --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/interval.proto @@ -0,0 +1,46 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +import "google/protobuf/timestamp.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/interval;interval"; +option java_multiple_files = true; +option java_outer_classname = "IntervalProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a time interval, encoded as a Timestamp start (inclusive) and a +// Timestamp end (exclusive). +// +// The start must be less than or equal to the end. +// When the start equals the end, the interval is empty (matches no time). +// When both start and end are unspecified, the interval matches any time. +message Interval { + // Optional. Inclusive start of the interval. + // + // If specified, a Timestamp matching this interval will have to be the same + // or after the start. + google.protobuf.Timestamp start_time = 1; + + // Optional. Exclusive end of the interval. + // + // If specified, a Timestamp matching this interval will have to be before the + // end. + google.protobuf.Timestamp end_time = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/latlng.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/latlng.proto new file mode 100644 index 00000000..9231456e --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/latlng.proto @@ -0,0 +1,37 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/latlng;latlng"; +option java_multiple_files = true; +option java_outer_classname = "LatLngProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// An object that represents a latitude/longitude pair. This is expressed as a +// pair of doubles to represent degrees latitude and degrees longitude. Unless +// specified otherwise, this must conform to the +// WGS84 +// standard. Values must be within normalized ranges. +message LatLng { + // The latitude in degrees. It must be in the range [-90.0, +90.0]. + double latitude = 1; + + // The longitude in degrees. It must be in the range [-180.0, +180.0]. + double longitude = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/localized_text.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/localized_text.proto new file mode 100644 index 00000000..5c6922b8 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/localized_text.proto @@ -0,0 +1,36 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/localized_text;localized_text"; +option java_multiple_files = true; +option java_outer_classname = "LocalizedTextProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Localized variant of a text in a particular language. +message LocalizedText { + // Localized string in the language corresponding to `language_code' below. + string text = 1; + + // The text's BCP-47 language code, such as "en-US" or "sr-Latn". + // + // For more information, see + // http://www.unicode.org/reports/tr35/#Unicode_locale_identifier. + string language_code = 2; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/money.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/money.proto new file mode 100644 index 00000000..98d6494e --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/money.proto @@ -0,0 +1,42 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/money;money"; +option java_multiple_files = true; +option java_outer_classname = "MoneyProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents an amount of money with its currency type. +message Money { + // The three-letter currency code defined in ISO 4217. + string currency_code = 1; + + // The whole units of the amount. + // For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar. + int64 units = 2; + + // Number of nano (10^-9) units of the amount. + // The value must be between -999,999,999 and +999,999,999 inclusive. + // If `units` is positive, `nanos` must be positive or zero. + // If `units` is zero, `nanos` can be positive, zero, or negative. + // If `units` is negative, `nanos` must be negative or zero. + // For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000. + int32 nanos = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/month.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/month.proto new file mode 100644 index 00000000..99e7551b --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/month.proto @@ -0,0 +1,65 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option go_package = "google.golang.org/genproto/googleapis/type/month;month"; +option java_multiple_files = true; +option java_outer_classname = "MonthProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a month in the Gregorian calendar. +enum Month { + // The unspecified month. + MONTH_UNSPECIFIED = 0; + + // The month of January. + JANUARY = 1; + + // The month of February. + FEBRUARY = 2; + + // The month of March. + MARCH = 3; + + // The month of April. + APRIL = 4; + + // The month of May. + MAY = 5; + + // The month of June. + JUNE = 6; + + // The month of July. + JULY = 7; + + // The month of August. + AUGUST = 8; + + // The month of September. + SEPTEMBER = 9; + + // The month of October. + OCTOBER = 10; + + // The month of November. + NOVEMBER = 11; + + // The month of December. + DECEMBER = 12; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/phone_number.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/phone_number.proto new file mode 100644 index 00000000..7bbb7d87 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/phone_number.proto @@ -0,0 +1,113 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/phone_number;phone_number"; +option java_multiple_files = true; +option java_outer_classname = "PhoneNumberProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// An object representing a phone number, suitable as an API wire format. +// +// This representation: +// +// - should not be used for locale-specific formatting of a phone number, such +// as "+1 (650) 253-0000 ext. 123" +// +// - is not designed for efficient storage +// - may not be suitable for dialing - specialized libraries (see references) +// should be used to parse the number for that purpose +// +// To do something meaningful with this number, such as format it for various +// use-cases, convert it to an `i18n.phonenumbers.PhoneNumber` object first. +// +// For instance, in Java this would be: +// +// com.google.type.PhoneNumber wireProto = +// com.google.type.PhoneNumber.newBuilder().build(); +// com.google.i18n.phonenumbers.Phonenumber.PhoneNumber phoneNumber = +// PhoneNumberUtil.getInstance().parse(wireProto.getE164Number(), "ZZ"); +// if (!wireProto.getExtension().isEmpty()) { +// phoneNumber.setExtension(wireProto.getExtension()); +// } +// +// Reference(s): +// - https://github.com/google/libphonenumber +message PhoneNumber { + // An object representing a short code, which is a phone number that is + // typically much shorter than regular phone numbers and can be used to + // address messages in MMS and SMS systems, as well as for abbreviated dialing + // (e.g. "Text 611 to see how many minutes you have remaining on your plan."). + // + // Short codes are restricted to a region and are not internationally + // dialable, which means the same short code can exist in different regions, + // with different usage and pricing, even if those regions share the same + // country calling code (e.g. US and CA). + message ShortCode { + // Required. The BCP-47 region code of the location where calls to this + // short code can be made, such as "US" and "BB". + // + // Reference(s): + // - http://www.unicode.org/reports/tr35/#unicode_region_subtag + string region_code = 1; + + // Required. The short code digits, without a leading plus ('+') or country + // calling code, e.g. "611". + string number = 2; + } + + // Required. Either a regular number, or a short code. New fields may be + // added to the oneof below in the future, so clients should ignore phone + // numbers for which none of the fields they coded against are set. + oneof kind { + // The phone number, represented as a leading plus sign ('+'), followed by a + // phone number that uses a relaxed ITU E.164 format consisting of the + // country calling code (1 to 3 digits) and the subscriber number, with no + // additional spaces or formatting, e.g.: + // - correct: "+15552220123" + // - incorrect: "+1 (555) 222-01234 x123". + // + // The ITU E.164 format limits the latter to 12 digits, but in practice not + // all countries respect that, so we relax that restriction here. + // National-only numbers are not allowed. + // + // References: + // - https://www.itu.int/rec/T-REC-E.164-201011-I + // - https://en.wikipedia.org/wiki/E.164. + // - https://en.wikipedia.org/wiki/List_of_country_calling_codes + string e164_number = 1; + + // A short code. + // + // Reference(s): + // - https://en.wikipedia.org/wiki/Short_code + ShortCode short_code = 2; + } + + // The phone number's extension. The extension is not standardized in ITU + // recommendations, except for being defined as a series of numbers with a + // maximum length of 40 digits. Other than digits, some other dialing + // characters such as ',' (indicating a wait) or '#' may be stored here. + // + // Note that no regions currently use extensions with short codes, so this + // field is normally only set in conjunction with an E.164 number. It is held + // separately from the E.164 number to allow for short code extensions in the + // future. + string extension = 3; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/postal_address.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/postal_address.proto new file mode 100644 index 00000000..c57c7c31 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/postal_address.proto @@ -0,0 +1,134 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/postaladdress;postaladdress"; +option java_multiple_files = true; +option java_outer_classname = "PostalAddressProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a postal address, e.g. for postal delivery or payments addresses. +// Given a postal address, a postal service can deliver items to a premise, P.O. +// Box or similar. +// It is not intended to model geographical locations (roads, towns, +// mountains). +// +// In typical usage an address would be created via user input or from importing +// existing data, depending on the type of process. +// +// Advice on address input / editing: +// - Use an i18n-ready address widget such as +// https://github.com/google/libaddressinput) +// - Users should not be presented with UI elements for input or editing of +// fields outside countries where that field is used. +// +// For more guidance on how to use this schema, please see: +// https://support.google.com/business/answer/6397478 +message PostalAddress { + // The schema revision of the `PostalAddress`. This must be set to 0, which is + // the latest revision. + // + // All new revisions **must** be backward compatible with old revisions. + int32 revision = 1; + + // Required. CLDR region code of the country/region of the address. This + // is never inferred and it is up to the user to ensure the value is + // correct. See http://cldr.unicode.org/ and + // http://www.unicode.org/cldr/charts/30/supplemental/territory_information.html + // for details. Example: "CH" for Switzerland. + string region_code = 2; + + // Optional. BCP-47 language code of the contents of this address (if + // known). This is often the UI language of the input form or is expected + // to match one of the languages used in the address' country/region, or their + // transliterated equivalents. + // This can affect formatting in certain countries, but is not critical + // to the correctness of the data and will never affect any validation or + // other non-formatting related operations. + // + // If this value is not known, it should be omitted (rather than specifying a + // possibly incorrect default). + // + // Examples: "zh-Hant", "ja", "ja-Latn", "en". + string language_code = 3; + + // Optional. Postal code of the address. Not all countries use or require + // postal codes to be present, but where they are used, they may trigger + // additional validation with other parts of the address (e.g. state/zip + // validation in the U.S.A.). + string postal_code = 4; + + // Optional. Additional, country-specific, sorting code. This is not used + // in most regions. Where it is used, the value is either a string like + // "CEDEX", optionally followed by a number (e.g. "CEDEX 7"), or just a number + // alone, representing the "sector code" (Jamaica), "delivery area indicator" + // (Malawi) or "post office indicator" (e.g. Côte d'Ivoire). + string sorting_code = 5; + + // Optional. Highest administrative subdivision which is used for postal + // addresses of a country or region. + // For example, this can be a state, a province, an oblast, or a prefecture. + // Specifically, for Spain this is the province and not the autonomous + // community (e.g. "Barcelona" and not "Catalonia"). + // Many countries don't use an administrative area in postal addresses. E.g. + // in Switzerland this should be left unpopulated. + string administrative_area = 6; + + // Optional. Generally refers to the city/town portion of the address. + // Examples: US city, IT comune, UK post town. + // In regions of the world where localities are not well defined or do not fit + // into this structure well, leave locality empty and use address_lines. + string locality = 7; + + // Optional. Sublocality of the address. + // For example, this can be neighborhoods, boroughs, districts. + string sublocality = 8; + + // Unstructured address lines describing the lower levels of an address. + // + // Because values in address_lines do not have type information and may + // sometimes contain multiple values in a single field (e.g. + // "Austin, TX"), it is important that the line order is clear. The order of + // address lines should be "envelope order" for the country/region of the + // address. In places where this can vary (e.g. Japan), address_language is + // used to make it explicit (e.g. "ja" for large-to-small ordering and + // "ja-Latn" or "en" for small-to-large). This way, the most specific line of + // an address can be selected based on the language. + // + // The minimum permitted structural representation of an address consists + // of a region_code with all remaining information placed in the + // address_lines. It would be possible to format such an address very + // approximately without geocoding, but no semantic reasoning could be + // made about any of the address components until it was at least + // partially resolved. + // + // Creating an address only containing a region_code and address_lines, and + // then geocoding is the recommended way to handle completely unstructured + // addresses (as opposed to guessing which parts of the address should be + // localities or administrative areas). + repeated string address_lines = 9; + + // Optional. The recipient at the address. + // This field may, under certain circumstances, contain multiline information. + // For example, it might contain "care of" information. + repeated string recipients = 10; + + // Optional. The name of the organization at the address. + string organization = 11; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/quaternion.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/quaternion.proto new file mode 100644 index 00000000..dfb822de --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/quaternion.proto @@ -0,0 +1,94 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/quaternion;quaternion"; +option java_multiple_files = true; +option java_outer_classname = "QuaternionProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// A quaternion is defined as the quotient of two directed lines in a +// three-dimensional space or equivalently as the quotient of two Euclidean +// vectors (https://en.wikipedia.org/wiki/Quaternion). +// +// Quaternions are often used in calculations involving three-dimensional +// rotations (https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation), +// as they provide greater mathematical robustness by avoiding the gimbal lock +// problems that can be encountered when using Euler angles +// (https://en.wikipedia.org/wiki/Gimbal_lock). +// +// Quaternions are generally represented in this form: +// +// w + xi + yj + zk +// +// where x, y, z, and w are real numbers, and i, j, and k are three imaginary +// numbers. +// +// Our naming choice `(x, y, z, w)` comes from the desire to avoid confusion for +// those interested in the geometric properties of the quaternion in the 3D +// Cartesian space. Other texts often use alternative names or subscripts, such +// as `(a, b, c, d)`, `(1, i, j, k)`, or `(0, 1, 2, 3)`, which are perhaps +// better suited for mathematical interpretations. +// +// To avoid any confusion, as well as to maintain compatibility with a large +// number of software libraries, the quaternions represented using the protocol +// buffer below *must* follow the Hamilton convention, which defines `ij = k` +// (i.e. a right-handed algebra), and therefore: +// +// i^2 = j^2 = k^2 = ijk = −1 +// ij = −ji = k +// jk = −kj = i +// ki = −ik = j +// +// Please DO NOT use this to represent quaternions that follow the JPL +// convention, or any of the other quaternion flavors out there. +// +// Definitions: +// +// - Quaternion norm (or magnitude): `sqrt(x^2 + y^2 + z^2 + w^2)`. +// - Unit (or normalized) quaternion: a quaternion whose norm is 1. +// - Pure quaternion: a quaternion whose scalar component (`w`) is 0. +// - Rotation quaternion: a unit quaternion used to represent rotation. +// - Orientation quaternion: a unit quaternion used to represent orientation. +// +// A quaternion can be normalized by dividing it by its norm. The resulting +// quaternion maintains the same direction, but has a norm of 1, i.e. it moves +// on the unit sphere. This is generally necessary for rotation and orientation +// quaternions, to avoid rounding errors: +// https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions +// +// Note that `(x, y, z, w)` and `(-x, -y, -z, -w)` represent the same rotation, +// but normalization would be even more useful, e.g. for comparison purposes, if +// it would produce a unique representation. It is thus recommended that `w` be +// kept positive, which can be achieved by changing all the signs when `w` is +// negative. +// +message Quaternion { + // The x component. + double x = 1; + + // The y component. + double y = 2; + + // The z component. + double z = 3; + + // The scalar component. + double w = 4; +} diff --git a/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/timeofday.proto b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/timeofday.proto new file mode 100644 index 00000000..5cb48aa9 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiExe/protos/google/type/timeofday.proto @@ -0,0 +1,44 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.type; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/type/timeofday;timeofday"; +option java_multiple_files = true; +option java_outer_classname = "TimeOfDayProto"; +option java_package = "com.google.type"; +option objc_class_prefix = "GTP"; + +// Represents a time of day. The date and time zone are either not significant +// or are specified elsewhere. An API may choose to allow leap seconds. Related +// types are [google.type.Date][google.type.Date] and +// `google.protobuf.Timestamp`. +message TimeOfDay { + // Hours of day in 24 hour format. Should be from 0 to 23. An API may choose + // to allow the value "24:00:00" for scenarios like business closing time. + int32 hours = 1; + + // Minutes of hour of day. Must be from 0 to 59. + int32 minutes = 2; + + // Seconds of minutes of the time. Must normally be from 0 to 59. An API may + // allow the value 60 if it allows leap-seconds. + int32 seconds = 3; + + // Fractions of seconds in nanoseconds. Must be from 0 to 999,999,999. + int32 nanos = 4; +} diff --git a/src/EcTranslators/VertexAi/VertexAiPromptExeTranslatorCommandLineArgs.cs b/src/EcTranslators/VertexAi/VertexAiPromptExeTranslatorCommandLineArgs.cs new file mode 100644 index 00000000..95e18936 --- /dev/null +++ b/src/EcTranslators/VertexAi/VertexAiPromptExeTranslatorCommandLineArgs.cs @@ -0,0 +1,17 @@ +// #define encryptingNewCredentials + +namespace SilEncConverters40.EcTranslators.VertexAi +{ + public class VertexAiPromptExeTranslatorCommandLineArgs : PromptExeTranslatorCommandLineArgs + { + public string ProjectId { get; set; } + public string LocationId { get; set; } + public string Publisher { get; set; } + public string ModelId { get; set; } + public double? Temperature { get; set; } = 0.3; // the default from vertex example + public int? MaxDecodeSteps { get; set; } = 200; // default + public double? TopP { get; set; } = 0.8; // default + public int? TopK { get; set; } = 40; // default + } +} + diff --git a/src/EcTranslators/app.config b/src/EcTranslators/app.config index a82e9dd6..66617a7d 100644 --- a/src/EcTranslators/app.config +++ b/src/EcTranslators/app.config @@ -23,11 +23,11 @@ - + - + @@ -35,11 +35,11 @@ - + - + @@ -47,31 +47,31 @@ - + - + - + - + - + - + - + @@ -149,6 +149,24 @@ + + + + + + + + + + + us-central1 + + + google + + + chat-bison + diff --git a/src/EncCnvtrs/EncConverters.cs b/src/EncCnvtrs/EncConverters.cs index c6c8f290..12e99e49 100755 --- a/src/EncCnvtrs/EncConverters.cs +++ b/src/EncCnvtrs/EncConverters.cs @@ -89,7 +89,7 @@ public class EncConverters : Hashtable, IEncConverters public const string strTypeSILDeepLTranslator = "SIL.DeepLTranslator"; public const string strTypeSILAzureOpenAiTranslator = "SIL.AzureOpenAI"; public const string strTypeSILNllbTranslator = "SIL.NllbTranslator"; - + public const string strTypeSILVertexAiTranslator = "SIL.VertexAi"; public const string cstrTempConverterPrefix = "Temporary Converter"; // default values for XML file attributes From db10ca0aa7bdb3b27589c1a2117a22d8e10e3889 Mon Sep 17 00:00:00 2001 From: bobeaton Date: Sat, 17 Feb 2024 08:14:00 +0530 Subject: [PATCH 089/113] added support to query for and send examples to use for Chat-Prompt-based translators (think: poor-man's fine tuning) --- .../BackTranslationHelper.csproj | 9 ++ .../BackTranslationHelperCtrl.cs | 142 +++++++++++++++--- .../BackTranslationHelperCtrl.designer.cs | 50 ++++-- .../BackTranslationHelperCtrl.resx | 6 + .../ExampleEditorDialog.Designer.cs | 140 +++++++++++++++++ .../ExampleEditorDialog.cs | 68 +++++++++ .../ExampleEditorDialog.resx | 120 +++++++++++++++ .../TranslatorListForm.Designer.cs | 12 +- 8 files changed, 502 insertions(+), 45 deletions(-) create mode 100644 src/BackTranslationHelper/ExampleEditorDialog.Designer.cs create mode 100644 src/BackTranslationHelper/ExampleEditorDialog.cs create mode 100644 src/BackTranslationHelper/ExampleEditorDialog.resx diff --git a/src/BackTranslationHelper/BackTranslationHelper.csproj b/src/BackTranslationHelper/BackTranslationHelper.csproj index a3bd3d05..2e2a264d 100644 --- a/src/BackTranslationHelper/BackTranslationHelper.csproj +++ b/src/BackTranslationHelper/BackTranslationHelper.csproj @@ -103,6 +103,12 @@ BackTranslationHelperCtrl.cs + + Form + + + ExampleEditorDialog.cs + @@ -116,6 +122,9 @@ TranslatorListForm.cs + + ExampleEditorDialog.cs + TranslatorListForm.cs diff --git a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs index cfd07cb9..ca7806e6 100644 --- a/src/BackTranslationHelper/BackTranslationHelperCtrl.cs +++ b/src/BackTranslationHelper/BackTranslationHelperCtrl.cs @@ -6,6 +6,8 @@ using System.Collections.Specialized; using System.Drawing; using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -18,7 +20,13 @@ public partial class BackTranslationHelperCtrl : UserControl // I could make the EcTranslator project a dependency to this project and use NllbEncConverter.CstrDisplayName instead, but... private const string NllbEncConverterDisplayName = "NLLB Translator"; - private const string NllbEncConverterSplitSentencesPrefix = @"\SplitSentences "; + + private readonly List PromptTranslatorConfiguratorDisplayNames = new List + { + "Azure OpenAI Translator", "Vertex AI Translator" + }; + + private const string NllbEncConverterSplitSentencesPrefix = @"\SplitSentences "; #region Member variables @@ -71,6 +79,7 @@ private void SettingsToolStripMenuItem_DropDownOpening(object sender, EventArgs { this.hideCurrentTargetTextToolStripMenuItem.Visible = (_model == null) || (_model.DisplayExistingTargetTranslation); this.SentenceSplittingMenuItem.Enabled = TheTranslators.Any(t => t.Configurator?.ConfiguratorDisplayName == NllbEncConverterDisplayName); + this.AddExampleMenuItem.Enabled = this.PurgeExamplesMenuItem.Enabled = PromptTranslators.Any(); } private void TargetBackTranslation_MouseWheel(object sender, MouseEventArgs e) @@ -168,13 +177,15 @@ public void Initialize(BackTranslationHelperModel model) var labelsPossibleTargetTranslations = tableLayoutPanel.Controls.OfType

    k+rM@~d;IC$g4EO1Q=`N=( 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�u0zZq&reb_gY$(C`3Pfbj&2l@A= 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image010.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image010.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df2f96f588fa7267cf0a26c48851e25b8e86ba5b GIT binary patch literal 36769 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image011.png b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image011.png new file mode 100644 index 0000000000000000000000000000000000000000..9b530602cdd493e0b9f624bc7a947332130ebba2 GIT binary patch literal 6834 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 Uz$X0AKs6n&-o0t3(Ud8>3q?cB*LA2^AC0c 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image015.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image015.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f39e609e183c93f2a01e8f5a190adc35e981333d GIT binary patch literal 36388 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 QbI*Em%Uwj7_{*pN0L{rP(*OVf literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image017.jpg b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/image017.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9ec2d0e1888774ce8b91719062a37a2d0fc7ca7a GIT binary patch literal 22096 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 literal 0 HcmV?d00001 diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0013.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0013.xml new file mode 100644 index 00000000..df14848b --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0013.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0016.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0016.xml new file mode 100644 index 00000000..df14848b --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0016.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0017.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0017.xml new file mode 100644 index 00000000..df14848b --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0017.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0018.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0018.xml new file mode 100644 index 00000000..df14848b --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/item0018.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props014.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props014.xml new file mode 100644 index 00000000..9621d74e --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props014.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props017.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props017.xml new file mode 100644 index 00000000..9621d74e --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props017.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props018.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props018.xml new file mode 100644 index 00000000..9621d74e --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props018.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props019.xml b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props019.xml new file mode 100644 index 00000000..9621d74e --- /dev/null +++ b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/props019.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/themedata.thmx b/redist/Help/Vertex_AI_Translate_Plug-in_About_box_files/themedata.thmx new file mode 100644 index 0000000000000000000000000000000000000000..3d2a4372ca5888704157184c6edc22884c62dae9 GIT binary patch literal 3339 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 literal 0 HcmV?d00001 diff --git a/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs b/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs index 52665573..8bdc0287 100644 --- a/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs +++ b/src/EcTranslators/AzureOpenAi/AzureOpenAiEncConverter.cs @@ -29,8 +29,8 @@ namespace SilEncConverters40.EcTranslators.AzureOpenAI #else [GuidAttribute("74EC9437-A9F1-44B3-BA70-5A8055E210D9")] #endif - public class AzureOpenAiEncConverter : ExeEncConverter - { + public class AzureOpenAiEncConverter : PromptExeTranslator + { #region Member Variable Definitions protected string AiSystemInstructions; @@ -95,14 +95,11 @@ public static string AzureOpenAiKeyOverride ///