EduNetworkBuilder/EduNetworkBuilder/TranslationWindow.cs

689 lines
26 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using System.Resources;
using System.Collections;
using System.ComponentModel.Design;
namespace EduNetworkBuilder
{
public partial class TranslationWindow : Form
{
Network myNet = null;
string[,] LanguageChoices = NB.LanguageChoices;
string FormChosenDir = "";
List<TranslationResxFile> TranslationResxFiles = new List<TranslationResxFile>();
List<TranslationFormData> FormData = new List<TranslationFormData>();
string EnglishTargetFile = "edustrings.resx";
bool ChangedFormData = false;
bool ChangedPuzzleData = false;
ToolTip myTooltip = new ToolTip();
public TranslationWindow(Network ToEdit)
{
InitializeComponent();
this.KeyPreview = true;
myNet = ToEdit;
LocalSetup();
}
void LocalSetup()
{
FillTranslationFormData();
myTooltip.AutoPopDelay = 5000;
myTooltip.InitialDelay = 1000;
myTooltip.ReshowDelay = 500;
cb1Language.Items.Clear();
cb2Language.Items.Clear();
cbFormLang1Choice.Items.Clear();
cbFormLang2Choice.Items.Clear();
cbFormHighPriority.CheckedChanged += PopulateFormTranslationItems;
cbFormShowTranslated.CheckedChanged += PopulateFormTranslationItems;
cbFormFilter.Items.Clear();
foreach(TranslationFormData TFD in FormData)
{
cbFormFilter.Items.Add(TFD.Prefix);
}
panelTranslateFormItems.Enabled = false;
NBSettings mySettings = NB.GetSettings();
//See if the file we are editing has the right folder. If so, we do not need to choose one
FormChosenDir = mySettings.FormLastTransDir;
if (!TryToChooseFormDir(FormChosenDir))
TryToChooseFormDir(Path.GetDirectoryName(myNet.NetworkFilename));
for (int i = 0; i < LanguageChoices.GetLength(0); i++)
{
cb1Language.Items.Add(LanguageChoices[i, 0]);
cb2Language.Items.Add(LanguageChoices[i, 0]);
cbFormLang1Choice.Items.Add(LanguageChoices[i, 0]);
cbFormLang2Choice.Items.Add(LanguageChoices[i, 0]);
if (mySettings.LastTrans1Lang == LanguageChoices[i, 1])
{
cb1Language.SelectedItem = LanguageChoices[i, 0];
cbFormLang1Choice.SelectedItem = LanguageChoices[i, 0];
}
if (mySettings.LastTrans2Lang == LanguageChoices[i, 1])
{
cb2Language.SelectedItem = LanguageChoices[i, 0];
cbFormLang2Choice.SelectedItem = LanguageChoices[i, 0];
}
}
if (cb1Language.SelectedIndex == -1) cb1Language.SelectedIndex = 0;
if (cb2Language.SelectedIndex == -1) cb2Language.SelectedIndex = 0;
Icon = Properties.Resources.NBIco;
lblStatus.Text = "";
LanguagifyComponents();
cbFormFilter.Text = "Any";
}
private void LanguagifyComponents()
{
Text = NB.Translate("TW_Translate");
btnSave.Text = NB.Translate("_Save");
btnClose.Text = NB.Translate("_Done");
tpMessageTitle.Text = NB.Translate("TW_Message");
tpFormStuff.Text = NB.Translate("TW_Form");
}
private void FillTranslationFormData()
{
FormData.Clear();
FormData.Add(new TranslationFormData("TW_", "Translation Window. The Window where translation into another language is done.", 1));
FormData.Add(new TranslationFormData("_", "Phrases which are used on multiple windows", 10));
FormData.Add(new TranslationFormData("Any", "Not Filtered by form", 0));
FormData.Add(new TranslationFormData("DC_", "Device Config Window. This is where you configure the switch, firewall, PC, etc.", 10));
FormData.Add(new TranslationFormData("H_", "The Help system.", 1));
FormData.Add(new TranslationFormData("IPAE_", "IP Address Editor. This is the IP Address Edit Window where you set the IP, subnet, gateway, etc", 9));
FormData.Add(new TranslationFormData("LBW_", "ListBox Window. This is mainly the list of puzzles.", 8));
FormData.Add(new TranslationFormData("LE_", "LinkEditor. This is where you define a network link between two devices", 6));
FormData.Add(new TranslationFormData("N_", "Network. The Network is basically the collection of devices, links, tests and the like. Most of the things translated are status or error messages.", 4));
FormData.Add(new TranslationFormData("NB_", "NetworkBuilder Window. This is the main window and the menus on that window.", 10));
FormData.Add(new TranslationFormData("NC_", "NetworkCard. The card itself mainly just generates error messages.", 4));
FormData.Add(new TranslationFormData("NCE_", "Network Card Editor. The window where you define the network card (VPN, Wireless card, etc)", 7));
FormData.Add(new TranslationFormData("ND_", "Network Device. The device is what generates most of the main error messages.", 8));
FormData.Add(new TranslationFormData("NI_", "Network Interface. This generates some error messages (VLAN, etc)", 3));
FormData.Add(new TranslationFormData("NL_", "Network Link. Generates some error messages when packets are corrupt.", 7));
FormData.Add(new TranslationFormData("NT_", "Network Test. These are the things that make the puzzles puzzling.", 10));
FormData.Add(new TranslationFormData("NTE_", "Network Test Editor. This is the window where you edit the network tests.", 2));
FormData.Add(new TranslationFormData("OW_", "Options Window. Where the puzzle options are configured. Teachers use this, but most students would not", 3));
FormData.Add(new TranslationFormData("Options_", "A few options which are used both on the options window, but also on the main window", 9));
FormData.Add(new TranslationFormData("P_", "Packet. The error messages that the packet itself generates.", 7));
FormData.Add(new TranslationFormData("PC_", "Person Class. When working with students and faculty.", 2));
FormData.Add(new TranslationFormData("PM_", "Packet Messages. The system for dealing with packet messages", 4));
FormData.Add(new TranslationFormData("PPF_", "Person Profile Form. When dealing with faculty / students.", 1));
FormData.Add(new TranslationFormData("RPC_", "Random Puzzle Chooser. The form for generating a random puzzle", 5));
FormData.Add(new TranslationFormData("RTFW_", "RichText Window. A multipurpose window. Used for displaying help or the puzzle description.", 7));
FormData.Sort((a, b) => a.Prefix.CompareTo(b.Prefix) );
}
private void ClosingStuff()
{
NBSettings mySettings = NB.GetSettings();
for (int i = 0; i < LanguageChoices.GetLength(0); i++)
{
if (cb1Language.Text == LanguageChoices[i, 0])
{
mySettings.LastTrans1Lang = LanguageChoices[i, 1];
}
if (cb2Language.Text == LanguageChoices[i, 0])
{
mySettings.LastTrans2Lang = LanguageChoices[i, 1];
}
mySettings.FormLastTransDir = FormChosenDir;
}
mySettings.Save();
}
string CodeFromLang(string language)
{
for (int i = 0; i < LanguageChoices.GetLength(0); i++)
{
if (language == LanguageChoices[i, 0]) return LanguageChoices[i, 1];
}
return "";
}
string LangFromCode(string Code)
{
for (int i = 0; i < LanguageChoices.GetLength(0); i++)
{
if (Code == LanguageChoices[i, 1]) return LanguageChoices[i, 0];
}
return "";
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
private void Save()
{
if (ChangedPuzzleData && File.Exists(myNet.NetworkFilename))
{
myNet.Save();
//Console.WriteLine("Saved");
lblStatus.Text = NB.Translate("_Saved");
}
if(ChangedFormData)
{
foreach (TranslationResxFile one in TranslationResxFiles)
one.Save();
ChangedFormData = false;
lblStatus.Text = NB.Translate("_Saved");
}
}
private void TranslationWindow_KeyDown(object sender, KeyEventArgs e)
{
if(e.Modifiers == Keys.Control && e.KeyCode == Keys.S)
{
//ctrl-s was pressed
Save();
}
}
private void TranslationWindow_FormClosing(object sender, FormClosingEventArgs e)
{
if(ChangedFormData || ChangedPuzzleData)
{
DialogResult answer = MessageBox.Show("Save?", "Save?", MessageBoxButtons.YesNoCancel);
if(answer == DialogResult.Cancel)
{
e.Cancel = true;
return;
}
if (answer == DialogResult.Yes)
Save();
}
ClosingStuff();
}
private void cb1Language_SelectedIndexChanged(object sender, EventArgs e)
{
string What = CodeFromLang(cb1Language.Text);
if (What != "")
{
tb1Message.Text = myNet.NetMessage.GetText(What);
tb1Title.Text = myNet.NetTitle.GetText(What);
tb1URL.Text = myNet.NetURL.GetText(What);
}
}
private void cb2Language_SelectedIndexChanged(object sender, EventArgs e)
{
string What = CodeFromLang(cb2Language.Text);
if (What != "")
{
tb2Message.Text = myNet.NetMessage.GetText(What);
tb2Title.Text = myNet.NetTitle.GetText(What);
tb2URL.Text = myNet.NetURL.GetText(What);
}
}
void RefreshContents()
{
cb1Language_SelectedIndexChanged(null, EventArgs.Empty);
cb2Language_SelectedIndexChanged(null, EventArgs.Empty);
lblStatus.Text = "";
}
private void tb1Message_Leave(object sender, EventArgs e)
{
string What = CodeFromLang(cb1Language.Text);
if (What != "")
{
if (tb1Message.Text != myNet.NetMessage.GetText(What))
{
ChangedPuzzleData = true;
myNet.NetMessage.ChangeText(What, tb1Message.Text);
}
}
RefreshContents();
}
private void tb2Message_Leave(object sender, EventArgs e)
{
string What = CodeFromLang(cb2Language.Text);
if (What != "")
{
if (tb2Message.Text != myNet.NetMessage.GetText(What))
{
ChangedPuzzleData = true;
myNet.NetMessage.ChangeText(What, tb2Message.Text);
}
}
RefreshContents();
}
private void btnSave_Click(object sender, EventArgs e)
{
Save();
}
private void tb1Title_Leave(object sender, EventArgs e)
{
string What = CodeFromLang(cb1Language.Text);
if (What != "")
{
myNet.NetTitle.ChangeText(What, tb1Title.Text);
}
RefreshContents();
}
private void tb2Title_Leave(object sender, EventArgs e)
{
string What = CodeFromLang(cb2Language.Text);
if (What != "")
{
myNet.NetTitle.ChangeText(What, tb2Title.Text);
}
RefreshContents();
}
private void tb1URL_Leave(object sender, EventArgs e)
{
string What = CodeFromLang(cb1Language.Text);
if (What != "")
{
myNet.NetURL.ChangeText(What, tb1URL.Text);
}
RefreshContents();
}
private void tb2URL_Leave(object sender, EventArgs e)
{
string What = CodeFromLang(cb2Language.Text);
if (What != "")
{
myNet.NetURL.ChangeText(What, tb2URL.Text);
}
RefreshContents();
}
#region Form Translation Stuff
//**********************************************************************//
//******************* Form Translation Things **************************//
//**********************************************************************//
bool TryToChooseFormDir(string Choice)
{
if (Choice == null || Choice == "") return false;
//We want to have a file named edustrings.resx there
//There may be other files: edustrings.fr.resx
//If these exist, we are OK. Otherwise, see if there is a "languages" dir and try that if it does exist
string toCheck = Path.GetFileName(Choice).ToLower();
if (File.Exists(Choice))
if (toCheck == EnglishTargetFile)
{
FormChosenDir = Path.GetDirectoryName(Choice);
LoadResxFiles();
panelTranslateFormItems.Enabled = true;
lblFormDir.Text = "Dir: " + FormChosenDir;
lblFormDir.AutoSize = true;
lblFormDir.MaximumSize = new Size(250, 200);
return true;
}
if(Directory.Exists(Choice))
{
//It is a directory. See if it has the correct file in it.
if (TryToChooseFormDir(Path.Combine(Choice, EnglishTargetFile)))
{
return true; //It was successful
}
//If we get here, it did not have the file. See if there is a "languages" directory
if (TryToChooseFormDir(Path.Combine(Choice, "languages", EnglishTargetFile)))
{
return true; //It was successful
}
}
return false;
}
void LoadResxFiles()
{
if (!Directory.Exists(FormChosenDir)) return;
var resxFiles = Directory.EnumerateFiles(FormChosenDir, "*.resx", SearchOption.AllDirectories);
TranslationResxFiles.Clear();
foreach (string currentFile in resxFiles)
{
TranslationResxFile TRF = new TranslationResxFile(currentFile);
TranslationResxFiles.Add(TRF);
}
//Add any resx files that do not exist, but should
for( int i=0; i< LanguageChoices.GetLength(0); i++)
{
TranslationResxFile one = FileFromLangCode(LanguageChoices[i, 1]);
if(one == null)
{
//We need to make an empty resx file
one = new TranslationResxFile();
one.language = LanguageChoices[i, 1];
string filename = "edustrings."+ LanguageChoices[i, 1] + ".resx";
one.filename = filename;
TranslationResxFiles.Add(one);
}
}
//Populate any missing entries.
TranslationResxFile EN = FileFromLangCode("en");
if(EN != null) //Being null had better not happen... But just in case.
{
TranslationItem tempTI = null;
foreach(TranslationResxFile TRF in TranslationResxFiles)
{
if (TRF.language == EN.language) continue; //skip eng since that is the master
//Make sure each language has each item that the Eng version has
foreach(TranslationItem TI in EN.Items)
{
tempTI = ItemFromKey(TRF, TI.Key);
if(tempTI == null) //It does not exist in this language. Add it
{
tempTI = new TranslationItem(TI);
tempTI.translated = false; //Make sure it is set to false.
TRF.Items.Add(tempTI);
ChangedFormData = true; //We have changed something. We want to be able to save it
}
}
}
}
//Populate the fields from our new data
PopulateFormTranslationItems();
}
void PopulateFormTranslationItems(object sender, EventArgs e)
{
PopulateFormTranslationItems();
}
private void PopulateFormTranslationItems()
{
cbFormItemChoice.Items.Clear();
TranslationResxFile en = FileFromLangCode("en");
List<string> Priorities = new List<string>() { };
foreach(TranslationFormData TFD in FormData)
{
if (TFD.Importance > 5) Priorities.Add(TFD.Prefix);
}
if(en != null)
{
foreach(TranslationItem TI in en.Items)
{
bool AddTranslated = false;
bool AddHigh = false;
if (cbFormFilter.Text != "Any")
{
if (!TI.Key.StartsWith(cbFormFilter.Text))
continue;//Skip it if it does not match the filter.
}
if (!TI.translated || cbFormShowTranslated.Checked)
AddTranslated = true;
if (cbFormHighPriority.Checked)
{
foreach(string one in Priorities)
{
if(TI.Key.StartsWith(one))
{
AddHigh = true;
break;
}
}
}
else
AddHigh = true;
if(AddTranslated && AddHigh)
cbFormItemChoice.Items.Add(TI.Key);
}
}
if(cbFormItemChoice.SelectedIndex <0)
{
if (cbFormItemChoice.Items.Count > 0)
cbFormItemChoice.SelectedIndex = 1;
}
else { cbFormItemChoice.Text = ""; }
}
private TranslationResxFile FileFromLangCode(string code)
{
foreach (TranslationResxFile one in TranslationResxFiles)
if (one.language == code) return one;
return null;
}
private TranslationItem ItemFromKey(TranslationResxFile File, string Key)
{
if (File == null) return null;
foreach(TranslationItem TI in File.Items)
{
if (TI.Key == Key)
return TI;
}
return null;
}
private TranslationItem GetEditedTranslationItem()
{
string code = CodeFromLang(cbFormLang2Choice.Text);
TranslationResxFile TRf = FileFromLangCode(code);
TranslationItem TI = ItemFromKey(TRf, cbFormItemChoice.Text);
return TI;
}
private void btnChooseDir_Click(object sender, EventArgs e)
{
string startingDir = FormChosenDir;
if (FormChosenDir == "" && File.Exists(myNet.NetworkFilename))
startingDir = Path.GetDirectoryName(myNet.NetworkFilename);
//Prompt for a directory.
OpenFileDialog ofd = NB.SelectDirectoryDialog("Directory with language files", startingDir);
if(ofd.FileName != "")
{
//try to see if the chosen filename has appropriate files. We need the English, at least
if(!TryToChooseFormDir(Path.GetDirectoryName(ofd.FileName)))
{
MessageBox.Show("Invalid Directory.");
}
}
}
private void cbFormItemChoice_SelectedIndexChanged(object sender, EventArgs e)
{
string code = CodeFromLang(cbFormLang1Choice.Text);
TranslationResxFile TRf = FileFromLangCode(code);
TranslationItem TI = ItemFromKey(TRf, cbFormItemChoice.Text);
if(TRf != null && TI != null)
{
tbFormItem1.Text = TI.Value;
}
code = CodeFromLang(cbFormLang2Choice.Text);
TRf = FileFromLangCode(code);
TI = ItemFromKey(TRf, cbFormItemChoice.Text);
if (TRf != null && TI != null)
{
tbFormItem2.Text = TI.Value;
cbFormItemTranslated.Checked = TI.translated;
}
}
private void cbFormItemTranslated_CheckedChanged(object sender, EventArgs e)
{
TranslationItem TI = GetEditedTranslationItem();
if(TI != null)
{
TI.translated = cbFormItemTranslated.Checked;
ChangedFormData = true;
}
}
private void tbFormItem2_Leave(object sender, EventArgs e)
{
//If the text no longer matches, we want to update it.
TranslationItem TI = GetEditedTranslationItem();
if (TI != null)
{
//only make a note if it has changed
if (TI.Value != tbFormItem2.Text)
{
TI.Value = tbFormItem2.Text;
ChangedFormData = true;
}
}
}
private void cbFormFilter_SelectedIndexChanged(object sender, EventArgs e)
{
//We want to filter the form based on what we have here.
PopulateFormTranslationItems();
string tooltip = "";
foreach(TranslationFormData one in FormData)
{
if(one.Prefix == cbFormFilter.Text)
{
tooltip = one.Description;
break;
}
}
myTooltip.SetToolTip(cbFormFilter,tooltip);
}
}
#endregion
#region TranslationClasses
public class TranslationItem
{
public string Key = "";
public string Value = "";
public string Comment = "";
public bool translated = false;
public TranslationItem() { }
public TranslationItem(TranslationItem Source)
{
Key = Source.Key;
Value = Source.Value;
Comment = Source.Comment;
translated = Source.translated;
}
}
public class TranslationResxFile
{
public string filename;
public List<TranslationItem> Items = new List<TranslationItem>();
public string language = "";
string beginning = "translated: ";
public TranslationResxFile() { }
public TranslationResxFile(string File)
{
filename = File;
Load();
string fn = Path.GetFileName(File);
if (fn == "edustrings.resx")
{
language = "en";
}
else
language = fn.Substring(11, 2);
}
void Load()
{
if(! File.Exists(filename))
{
//The file does not exist yet. Nothing to load. Exit gracefully
return;
}
Items.Clear();
ResXResourceReader InResx = new ResXResourceReader(filename);
InResx.UseResXDataNodes = true;
System.Reflection.Assembly currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
foreach (DictionaryEntry d in InResx)
{
ResXDataNode rdn = (ResXDataNode)d.Value;
TranslationItem TI = new TranslationItem();
TI.Comment = rdn.Comment;
if (TI.Comment.StartsWith(beginning))
{
//trim off the beginning "translated" tag
TI.Comment = rdn.Comment.Substring(0, beginning.Length - 1);
TI.translated = true;
}
TI.Key = rdn.Name;
TI.Value = (string)rdn.GetValue(new System.Reflection.AssemblyName[] { currentAssembly.GetName() });
Items.Add(TI);
}
Items.Sort((a,b) => a.Key.CompareTo(b.Key));
InResx.Close();
}
public void Save()
{
string tmpfile = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + "-tmp" + Path.GetExtension(filename));
ResXResourceWriter WriteResx = new ResXResourceWriter(tmpfile);
foreach (TranslationItem d in Items)
{
ResXDataNode rdn = new ResXDataNode(d.Key, d.Value);
if (d.translated)
rdn.Comment = beginning + d.Comment;
else
rdn.Comment = d.Comment;
WriteResx.AddResource(rdn);
//Console.WriteLine("Adding " + toWrite.Name);
}
WriteResx.Generate();
WriteResx.Close();
//If we have an error, we should have exited and gone to "catch."
//Proceed to put the new file
if(File.Exists(filename))
File.Delete(filename);
File.Move(tmpfile, filename);
}
}
public class TranslationFormData
{
public string Prefix;
public string Description;
public int Importance; //10 is most important, 0 is least important
public TranslationFormData(string prefix, string description, int importance)
{
Prefix = prefix;
Description = description;
Importance = importance;
}
}
#endregion
}