public string Translate(string normal, string id) { if (translations != null && !normal.Equals("<code>")) { string key = id; if (OutputIDs) { string tx = "ID lookup " + key + " Value " + (translations.ContainsKey(key) ? (translations[key] ?? "Null") : "Missing"); System.Diagnostics.Debug.WriteLine(tx); logger?.WriteLine(tx); } if (translations.ContainsKey(key)) { #if DEBUG return(translations[key] ?? normal.QuoteFirstAlphaDigit()); // debug more we quote them to show its not translated, else in release we just print #else return(translations[key] ?? normal); #endif } else { logger?.WriteLine(string.Format("{0}: {1} @", id, normal.EscapeControlChars().AlwaysQuoteString())); translations.Add(key, normal); //System.Diagnostics.Debug.WriteLine("*** Missing Translate ID: {0}: \"{1}\" => \"{2}\"", id, normal.EscapeControlChars(), "<" + normal.EscapeControlChars() + ">"); return(normal); } } else { return(normal); } }
public string Translate(string normal, string id) { if (translations != null && !normal.Equals("<code>")) { string key = id; if (translations.ContainsKey(key)) { #if DEBUG return(translations[key] ?? ('\'' + normal + '\'')); // debug more we quote them to show its not translated, else in release we just print #else return(translations[key] ?? normal); #endif } else { logger?.WriteLine(string.Format("{0}: {1} @", id, normal.EscapeControlChars().AlwaysQuoteString())); translations.Add(key, normal); //System.Diagnostics.Debug.WriteLine("*** Missing Translate ID: {0}: \"{1}\" => \"{2}\"", id, normal.EscapeControlChars(), "<" + normal.EscapeControlChars() + ">"); return(normal); } } else { return(normal); } }
// Translate string. Normal is the english text, ID is the ID to look up. // if translator is off english is returned. // any <code> items are returned as is. public string Translate(string english, string id) { if (translations != null && !english.Equals("<code>")) { string key = id; if (OutputIDs) { string tx = "ID lookup " + key + " Value " + (translations.ContainsKey(key) ? (translations[key] ?? "Null") : "Missing"); System.Diagnostics.Debug.WriteLine(tx); logger?.WriteLine(tx); } if (translations.ContainsKey(key)) { if (inuse != null) { inuse[key] = true; } if (CompareTranslatedToCode && originalenglish.ContainsKey(key) && originalenglish[key] != english) { var orgeng = originalenglish[key]; logger?.WriteLine($"Difference Key {key} code `{english}` translation `{orgeng}`"); } #if DEBUG return(translations[key] ?? english.QuoteFirstAlphaDigit()); // debug more we quote them to show its not translated, else in release we just print #else return(translations[key] ?? english); #endif } else { logger?.WriteLine(string.Format("{0}: {1} @", id, english.EscapeControlChars().AlwaysQuoteString())); english = "! " + english + " !"; // no id at all, use ! to indicate translations.Add(key, english); //System.Diagnostics.Debug.WriteLine("*** Missing Translate ID: {0}: \"{1}\" => \"{2}\"", id, normal.EscapeControlChars(), "<" + normal.EscapeControlChars() + ">"); return(english); } } else { return(english); } }
} // debug // You can call this multiple times if required for debugging purposes public void LoadTranslation(string language, CultureInfo uicurrent, string[] txfolders, int includesearchupdepth, string logdir, string includefolderreject = "\\bin", // use to reject include files in specific locations - for debugging bool loadorgenglish = false, // optional load original english and store bool loadfile = false // remember file where it came from ) { #if DEBUG if (logger != null) { logger.Dispose(); } logger = new LogToFile(); logger.SetFile(logdir, "translator-ids.log", false); #endif translations = null; // forget any originalenglish = null; originalfile = null; List <Tuple <string, string> > languages = EnumerateLanguages(txfolders); // uicurrent = CultureInfo.CreateSpecificCulture("it"); // debug Tuple <string, string> langsel = null; if (language == "Auto") { langsel = FindISOLanguage(languages, uicurrent.Name); if (langsel == null) { langsel = FindISOLanguage(languages, uicurrent.TwoLetterISOLanguageName); } } else { langsel = languages.Find(x => Path.GetFileNameWithoutExtension(x.Item2).Equals(language, StringComparison.InvariantCultureIgnoreCase)); } if (langsel == null) { return; } System.Diagnostics.Debug.WriteLine("Load Language " + langsel.Item2); logger?.WriteLine("Read " + langsel.Item2 + " from " + langsel.Item1); using (LineReader lr = new LineReader()) { string tlffile = Path.Combine(langsel.Item1, langsel.Item2); if (lr.Open(tlffile)) { translations = new Dictionary <string, string>(); originalenglish = new Dictionary <string, string>(); originalfile = new Dictionary <string, string>(); string prefix = ""; string line = null; while ((line = lr.ReadLine()) != null) { line = line.Trim(); if (line.StartsWith("Include", StringComparison.InvariantCultureIgnoreCase)) { line = line.Mid(7).Trim(); DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(tlffile)); string filename = null; string fileinroot = Path.Combine(di.FullName, line); if (File.Exists(fileinroot)) // first we prefer files in the same folder.. { filename = fileinroot; } else { di = di.GetDirectoryAbove(includesearchupdepth); // then search the tree, first jump up search depth amount try { FileInfo[] allFiles = Directory.EnumerateFiles(di.FullName, line, SearchOption.AllDirectories).Select(f => new FileInfo(f)).OrderBy(p => p.LastWriteTime).ToArray(); if (allFiles.Length > 0) { var selected = allFiles.Where((x) => !x.DirectoryName.Contains(includefolderreject)); // reject folders with this pattern..files if (selected.Count() > 0) { filename = selected.First().FullName; } } } catch { } } if (filename == null || !lr.Open(filename)) // if no file found, or can't open.. { logger?.WriteLine(string.Format("*** Cannot include {0}", line)); } else { logger?.WriteLine("Read " + filename); } } else if (line.Length > 0 && !line.StartsWith("//")) { StringParser s = new StringParser(line); string id = s.NextWord(" :"); if (id.Equals("SECTION")) { prefix = s.NextQuotedWord(" /"); } else { if (id.StartsWith(".") && prefix.HasChars()) { id = prefix + id; } else { prefix = id.Word(new char[] { '.' }); } if (s.IsCharMoveOn(':')) { string orgenglish = s.NextQuotedWord(replaceescape: true); // first is the original english version string foreign = null; bool err = false; if (s.IsStringMoveOn("=>")) { foreign = s.NextQuotedWord(replaceescape: true); err = foreign == null; } else if (s.IsCharMoveOn('@')) { foreign = null; } else { err = false; } if (err == true) { logger?.WriteLine(string.Format("*** Translator ID but no translation {0}", id)); System.Diagnostics.Debug.WriteLine("*** Translator ID but no translation {0}", id); } else { if (!translations.ContainsKey(id)) { //logger?.WriteLine(string.Format("New {0}: \"{1}\" => \"{2}\"", id, english, foreign)); translations[id] = foreign; if (loadorgenglish) { originalenglish[id] = orgenglish; } if (loadfile) { originalfile[id] = lr.CurrentFile; } } else { logger?.WriteLine(string.Format("*** Translator Repeat {0}", id)); } } } } } } } } }
private void DoExecute() // MAIN thread only.. { executing = true; System.Diagnostics.Stopwatch timetaken = new System.Diagnostics.Stopwatch(); timetaken.Start(); while (true) { if (progcurrent != null) { if (progcurrent.GetErrorList != null) // any errors pending, handle { actioncontroller.LogLine("Error: " + progcurrent.GetErrorList + Environment.NewLine + StackTrace()); TerminateToCloseAtEnd(); // terminate up to a close at end entry, which would have started this stack } else if (progcurrent.IsProgramFinished) // if current program ran out, cancel it { // this catches a LOOP without a statement at the end.. or a DO without a WHILE at the end.. if (progcurrent.ExecLevel > 0 && progcurrent.LevelUp(progcurrent.ExecLevel, null)) // see if we have any pending LOOP (or a DO without a while) and continue.. { continue; // errors or movement causes it to go back.. errors will be picked up above } TerminateCurrent(); } } while (progcurrent == null && progqueue.Count > 0) // if no program,but something in queue { progcurrent = progqueue[0]; progqueue.RemoveAt(0); if (progcurrent.variables != null) // if not null, its because its just been restarted after a call.. reset globals { progcurrent.Add(actioncontroller.Globals); // in case they have been updated... progcurrent.Add(progcurrent.ActionFile.FileVariables); // in case they have been updated... } else { progcurrent.PrepareToRun( new Variables(progcurrent.inputvariables, actioncontroller.Globals, progcurrent.ActionFile.FileVariables), new FunctionPersistentData(), new Dictionary <string, ExtendedControls.ConfigurableForm>(), true); // with new file handles and close at end.. } if (progcurrent.IsProgramFinished) // reject empty programs.. { TerminateCurrent(); continue; // and try again } } if (progcurrent == null) // Still nothing, game over { break; } ActionBase ac = progcurrent.GetNextStep(); // get the step. move PC on. // System.Diagnostics.Debug.WriteLine((Environment.TickCount % 10000).ToString("00000") + " " + timetaken.ElapsedMilliseconds + " @ " + progcurrent.Location + " Lv " + progcurrent.ExecLevel + " e " + (progcurrent.IsExecuteOn ? "1" : "0") + " up " + ac.LevelUp + " " + progcurrent.PushPos + " " + ac.Name); if (ac.LevelUp > 0 && progcurrent.LevelUp(ac.LevelUp, ac)) // level up.. { //System.Diagnostics.Debug.WriteLine((Environment.TickCount % 10000).ToString("00000") + " Abort Lv" + progcurrent.ExecLevel + " e " + (progcurrent.IsExecuteOn ? "1" : "0") + " up " + ac.LevelUp + ": " + progcurrent.StepNumber + " " + ac.Name + " " + ac.DisplayedUserData); continue; } if (logtologline || logger != null) { string t = (Environment.TickCount % 10000).ToString("00000") + " "; string index = string.Concat(Enumerable.Repeat(". ", progcurrent.ExecLevel)); string s = progcurrent.GetLastStep().LineNumber.ToString() + (progcurrent.IsExecuteOn ? "+" : "-") + ":" + index + ac.Name + " " + ac.DisplayedUserData; System.Diagnostics.Debug.WriteLine(t + s); if (logtologline) { actioncontroller.LogLine(t + s); } if (logger != null) { logger.WriteLine(s); } } if (progcurrent.DoExecute(ac)) // execute is on.. { if (ac.Type == ActionBase.ActionType.Call) // Call needs to pass info back up thru to us, need a different call { ActionCall acall = ac as ActionCall; string prog; Variables paravars; if (acall.ExecuteCallAction(progcurrent, out prog, out paravars)) // if execute ok { //System.Diagnostics.Debug.WriteLine("Call " + prog + " with " + paravars.ToString()); Tuple <ActionFile, ActionProgram> ap = actionfilelist.FindProgram(prog, progcurrent.ActionFile); // find program using this name, prefer this action file first if (ap != null) { Run(true, ap.Item1, ap.Item2, paravars, progcurrent.Functions.persistentdata, progcurrent.Dialogs, false); // run now with these para vars } else { progcurrent.ReportError("Call cannot find " + prog); } } } else if (ac.Type == ActionBase.ActionType.Return) // Return needs to pass info back up thru to us, need a different call { ActionReturn ar = ac as ActionReturn; string retstr; if (ar.ExecuteActionReturn(progcurrent, out retstr)) { TerminateCurrent(); // if a new program is queued, but not prepared, and this program returns to finish, make sure we don't // screw up since the variables are not preparred yet - they will be above in PrepareToRun if (progqueue.Count > 0 && progqueue[0].variables != null) // pass return value if program is there AND its prepared { progqueue[0]["ReturnValue"] = retstr; } continue; // back to top, next action from returned function. } } else if (!ac.ExecuteAction(progcurrent)) // if execute says, stop, i'm waiting for something { return; // exit, with executing set true. ResumeAfterPause will restart it. } } if (AsyncMode && timetaken.ElapsedMilliseconds > 150) // no more than ms per go to stop the main thread being blocked { System.Diagnostics.Debug.WriteLine((Environment.TickCount % 10000).ToString("00000") + " *** SUSPEND Actions at " + timetaken.ElapsedMilliseconds); restarttick.Start(); break; } } executing = false; }
// You can call this multiple times if required for debugging purposes public void LoadTranslation(string language, CultureInfo uicurrent, string writabletxfolder1, string txfolder2) { #if DEBUG if (logger != null) { logger.Dispose(); } logger = new LogToFile(); logger.SetFile(writabletxfolder1, "ids.txt", false); #endif translations = null; // forget any List <string> languagesfolder1 = Languages(writabletxfolder1, false); // full paths List <string> languagesfolder2 = Languages(txfolder2, false); // uicurrent = CultureInfo.CreateSpecificCulture("es"); // debug string langfile = null; if (language == "Auto") { langfile = FindLanguage(languagesfolder1, uicurrent.Name); if (langfile == null) { langfile = FindLanguage(languagesfolder2, uicurrent.Name); } if (language == null) { langfile = FindLanguage(languagesfolder1, uicurrent.TwoLetterISOLanguageName); } if (language == null) { langfile = FindLanguage(languagesfolder2, uicurrent.TwoLetterISOLanguageName); } if (langfile == null) { return; } } else { langfile = Path.Combine(writabletxfolder1, language + ".tlf"); if (!File.Exists(langfile)) { langfile = Path.Combine(txfolder2, language + ".tlf"); if (!File.Exists(langfile)) { return; } } } System.Diagnostics.Debug.WriteLine("Load Language " + langfile); logger?.WriteLine("Read " + langfile); try { var utc8nobom = new UTF8Encoding(false); // give it the default UTF8 no BOM encoding, it will detect BOM or UCS-2 automatically StreamReader sr = new StreamReader(langfile, utc8nobom); translations = new Dictionary <string, string>(); string prefix = ""; string line = null; while ((line = sr.ReadLine()) != null) { line = line.Trim(); if (line.Length > 0 && !line.StartsWith("//")) { StringParser s = new StringParser(line); string id = s.NextWord(" :"); if (id.StartsWith(".") && prefix.HasChars()) { id = prefix + id; } else { prefix = id.Word(new char[] { '.' }); } if (s.IsCharMoveOn(':')) { s.NextQuotedWord(replaceescape: true); // ignore the english for ref purposes only string foreign = null; bool err = false; if (s.IsStringMoveOn("=>")) { foreign = s.NextQuotedWord(replaceescape: true); err = foreign == null; } else if (s.IsCharMoveOn('@')) { foreign = null; } else { err = false; } if (err == true) { logger?.WriteLine(string.Format("*** Translator ID but no translation {0}", id)); System.Diagnostics.Debug.WriteLine("*** Translator ID but no translation {0}", id); } else { if (!translations.ContainsKey(id)) { //logger?.WriteLine(string.Format("New {0}: \"{1}\" => \"{2}\"", id, english, foreign)); translations[id] = foreign; } else { logger?.WriteLine(string.Format("*** Translator Repeat {0}", id)); } } } } } } catch { } }
// You can call this multiple times if required for debugging purposes public void LoadTranslation(string language, CultureInfo uicurrent, string txfolder1, string txfolder2, int includesearchupdepth, string logdir) { #if DEBUG if (logger != null) { logger.Dispose(); } logger = new LogToFile(); logger.SetFile(logdir, "translator-ids.log", false); #endif translations = null; // forget any List <string> languagesfolder1 = Languages(txfolder1, false); // full paths List <string> languagesfolder2 = Languages(txfolder2, false); // uicurrent = CultureInfo.CreateSpecificCulture("es"); // debug string langfile = null; if (language == "Auto") { langfile = FindLanguage(languagesfolder1, uicurrent.Name); if (langfile == null) { langfile = FindLanguage(languagesfolder2, uicurrent.Name); } if (language == null) { langfile = FindLanguage(languagesfolder1, uicurrent.TwoLetterISOLanguageName); } if (language == null) { langfile = FindLanguage(languagesfolder2, uicurrent.TwoLetterISOLanguageName); } if (langfile == null) { return; } } else { langfile = Path.Combine(txfolder1, language + ".tlf"); if (!File.Exists(langfile)) { langfile = Path.Combine(txfolder2, language + ".tlf"); if (!File.Exists(langfile)) { return; } } } System.Diagnostics.Debug.WriteLine("Load Language " + langfile); logger?.WriteLine("Read " + langfile); using (LineReader lr = new LineReader()) { if (lr.Open(langfile)) { translations = new Dictionary <string, string>(); string prefix = ""; string line = null; while ((line = lr.ReadLine()) != null) { line = line.Trim(); if (line.StartsWith("Include", StringComparison.InvariantCultureIgnoreCase)) { line = line.Mid(7).Trim(); DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(langfile)); string filename = null; if (File.Exists(Path.Combine(di.FullName, line))) // first we prefer files in the same folder.. { filename = Path.Combine(di.FullName, line); } else { di = di.GetDirectoryAbove(includesearchupdepth); // then search the tree, first jump up search depth amount try { FileInfo[] allFiles = Directory.EnumerateFiles(di.FullName, line, SearchOption.AllDirectories).Select(f => new FileInfo(f)).OrderBy(p => p.LastWriteTime).ToArray(); if (allFiles.Length == 1) { filename = allFiles[0].FullName; } } catch { } } if (filename == null || !lr.Open(filename)) // if no file found, or can't open.. { logger?.WriteLine(string.Format("*** Cannot include {0}", line)); } else { logger?.WriteLine("Read " + filename); } } else if (line.Length > 0 && !line.StartsWith("//")) { StringParser s = new StringParser(line); string id = s.NextWord(" :"); if (id.StartsWith(".") && prefix.HasChars()) { id = prefix + id; } else { prefix = id.Word(new char[] { '.' }); } if (s.IsCharMoveOn(':')) { s.NextQuotedWord(replaceescape: true); // ignore the english for ref purposes only string foreign = null; bool err = false; if (s.IsStringMoveOn("=>")) { foreign = s.NextQuotedWord(replaceescape: true); err = foreign == null; } else if (s.IsCharMoveOn('@')) { foreign = null; } else { err = false; } if (err == true) { logger?.WriteLine(string.Format("*** Translator ID but no translation {0}", id)); System.Diagnostics.Debug.WriteLine("*** Translator ID but no translation {0}", id); } else { if (!translations.ContainsKey(id)) { //logger?.WriteLine(string.Format("New {0}: \"{1}\" => \"{2}\"", id, english, foreign)); translations[id] = foreign; } else { logger?.WriteLine(string.Format("*** Translator Repeat {0}", id)); } } } } } } } }