Skip to content

Commit

Permalink
Journal entries are translated
Browse files Browse the repository at this point in the history
Massive work to add tx to translator and update the lang file to cover these.

There will be bugs!

EDDiscovery/translator has an example file

This is not final
  • Loading branch information
robbyxp1 committed Jul 11, 2018
1 parent d5eaec6 commit b70f462
Show file tree
Hide file tree
Showing 199 changed files with 3,711 additions and 2,027 deletions.
1 change: 1 addition & 0 deletions BaseUtils/Misc/CommandArgs.cs
Expand Up @@ -26,6 +26,7 @@ public CommandArgs(CommandArgs other)
public string Next { get { return (pos < args.Length) ? args[pos++] : null; } }
public int Int { get { return (pos < args.Length) ? args[pos++].InvariantParseInt(0) : 0; } }
public string this[int v] { get { int left = args.Length - pos; return (v < left) ? args[pos + v] : null; } }
public bool More { get { return args.Length > pos; } }
public int Left { get { return args.Length - pos; } }
public void Remove() { if (pos < args.Length) pos++; }
}
Expand Down
27 changes: 23 additions & 4 deletions BaseUtils/Strings/StringObjectExtensions.cs
Expand Up @@ -131,18 +131,37 @@ public static string ReplaceUnderscoresNull(this object obj)
}
}

public static string ReplaceNonAlphaNumeric(this string obj)
public static string FirstAlphaNumericText(this string obj) // skip to find first alpha text ignoring whitespace
{
if (obj == null)
return null;
else
{
char[] arr = obj.ToCharArray();
arr = Array.FindAll<char>(arr, (c => char.IsLetterOrDigit(c)));
return new string(arr);
string ret = "";
int i = 0;
while (i < obj.Length && !char.IsLetterOrDigit(obj[i]))
i++;

for(; i < obj.Length; i++)
{
if (char.IsLetterOrDigit(obj[i]))
ret += obj[i];
else if (!char.IsWhiteSpace(obj[i]) )
break;
}

return ret;

}
}

public static string ReplaceNonAlphaNumeric(this string obj)
{
char[] arr = obj.ToCharArray();
arr = Array.FindAll<char>(arr, (c => char.IsLetterOrDigit(c)));
return new string(arr);
}

public static string QuoteString(this string obj, bool comma = false, bool bracket = false, bool space = true)
{
if (obj.Length == 0 || obj.Contains("\"") || obj[obj.Length - 1] == ' ' || (space && obj.Contains(" ")) || (bracket && obj.Contains(")")) || (comma && obj.Contains(",")))
Expand Down
163 changes: 99 additions & 64 deletions BaseUtils/Translator/Translator.cs
Expand Up @@ -11,22 +11,32 @@ public static class TranslatorExtensions
{
static public string Tx(this string s) // use the text, alpha numeric only, as the translation id
{
return BaseUtils.Translator.Instance.Translate(s, s.ReplaceNonAlphaNumeric());
return BaseUtils.Translator.Instance.Translate(s, s.FirstAlphaNumericText());
}

static public string Tx(this string s, Object c, string id) // use the type plus an id
{
return BaseUtils.Translator.Instance.Translate(s, c.GetType().Name, id);
}

static public string Txb(this string s, Object c, string id) // use the base type plus an id
{
return BaseUtils.Translator.Instance.Translate(s, c.GetType().BaseType.Name, id);
}

static public string Tx(this string s, Type c) // use a type definition using the string as the id
{
return BaseUtils.Translator.Instance.Translate(s, c.Name, s.ReplaceNonAlphaNumeric());
return BaseUtils.Translator.Instance.Translate(s, c.Name, s.FirstAlphaNumericText());
}

static public string Tx(this string s, Object c) // use the object type with string as id
{
return BaseUtils.Translator.Instance.Translate(s, c.GetType().Name, s.ReplaceNonAlphaNumeric());
return BaseUtils.Translator.Instance.Translate(s, c.GetType().Name, s.FirstAlphaNumericText());
}

static public string Txb(this string s, Object c) // use the base type using the string as the id
{
return BaseUtils.Translator.Instance.Translate(s, c.GetType().BaseType.Name, s.FirstAlphaNumericText());
}

static public string Tx(this string s, Type c, string id) // use a type definition with id
Expand All @@ -40,7 +50,7 @@ namespace BaseUtils
{
// specials : if text in a control = <code> its presumed its a code filled in entry and not suitable for translation
// in translator file, .Label means use the previous first word prefix stored, for shortness
// using Label: "English" @ means for debug, replace @ with <english> as the foreign word
// using Label: "English" @ means for debug, replace @ with <english> as the foreign word in the debug build. In release, just use the in-code text

public class Translator
{
Expand All @@ -55,7 +65,7 @@ public class Translator

LogToFile logger = null;

Dictionary<string, string> translations = null;
Dictionary<string, string> translations = null; // translation result can be null, which means, use the in-game english string
List<string> ExcludedControls = new List<string>();

private Translator()
Expand All @@ -64,138 +74,163 @@ private Translator()

// You can call this multiple times if required for debugging purposes

public void LoadTranslation(string language, CultureInfo uicurrent, string txfolder)
public void LoadTranslation(string language, CultureInfo uicurrent, string writabletxfolder1, string txfolder2)
{
#if DEBUG
if (logger != null)
logger.Dispose();

logger = new LogToFile();
logger.SetFile(txfolder, "ids.txt", false);
logger.SetFile(writabletxfolder1, "ids.txt", false);
#endif
translations = null; // forget any

List<string> languages = Languages(txfolder);
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")
{
language = FindLanguage(languages, uicurrent.Name);
langfile = FindLanguage(languagesfolder1, uicurrent.Name);

if (langfile == null)
langfile = FindLanguage(languagesfolder2, uicurrent.Name);

if (language == null)
language = FindLanguage(languages, uicurrent.TwoLetterISOLanguageName);
langfile = FindLanguage(languagesfolder1, uicurrent.TwoLetterISOLanguageName);

if (language == null)
langfile = FindLanguage(languagesfolder2, uicurrent.TwoLetterISOLanguageName);

if (langfile == null)
return;
}

string langfile = Path.Combine(txfolder, language + ".tlf");

if (File.Exists(langfile))
else
{
System.Diagnostics.Debug.WriteLine("Load Language " + langfile);
logger?.WriteLine("Read " + langfile);
langfile = Path.Combine(writabletxfolder1, language + ".tlf");

try
if (!File.Exists(langfile))
{
var utc8nobom = new UTF8Encoding(false); // give it the default UTF8 no BOM encoding, it will detect BOM or UCS-2 automatically
langfile = Path.Combine(txfolder2, language + ".tlf");

StreamReader sr = new StreamReader(langfile, utc8nobom);
if (!File.Exists(langfile))
return;
}
}

translations = new Dictionary<string, string>();
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

string prefix = "";
StreamReader sr = new StreamReader(langfile, utc8nobom);

string line = null;
while ((line = sr.ReadLine()) != null)
translations = new Dictionary<string, string>();

string prefix = "";

string line = null;
while ((line = sr.ReadLine()) != null)
{
line = line.Trim();
if (line.Length > 0 && !line.StartsWith("//"))
{
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(':'))
{
StringParser s = new StringParser(line);
s.NextQuotedWord(replaceescape: true); // ignore the english for ref purposes only

string id = s.NextWord(" :").ToLower();
string foreign = null;
bool err = false;

if (s.IsCharMoveOn(':'))
if (s.IsStringMoveOn("=>"))
{
string english = s.NextQuotedWord(replaceescape: true);
string foreign = null;

if (s.IsStringMoveOn("=>"))
foreign = s.NextQuotedWord(replaceescape: true);
else if (s.IsCharMoveOn('@')) // debug marker
foreign = "<" + english + ">";
foreign = s.NextQuotedWord(replaceescape: true);
err = foreign == null;
}
else if (s.IsCharMoveOn('@'))
foreign = null;
else
err = false;

if (foreign != null)
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))
{
// System.Diagnostics.Debug.WriteLine("{0}: {1} => {2}", id, english, foreign);

// make LF work

if (id.StartsWith(".") && prefix.HasChars())
id = prefix + id;
else
prefix = id.Word(new char[] { '.' });

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}: \"{1}\" => \"{2}\"", id, english, foreign));
System.Diagnostics.Debug.WriteLine("*** Translator Repeat {0}: {1} => {2}", id, english, foreign);
}
//logger?.WriteLine(string.Format("New {0}: \"{1}\" => \"{2}\"", id, english, foreign));
translations[id] = foreign;
}
else
{
logger?.WriteLine(string.Format("*** Translator ID but no translation \"{0}\": \"{1}\"", id, english));
System.Diagnostics.Debug.WriteLine("*** Translator ID but no translation {0}: {1}", id, english);
logger?.WriteLine(string.Format("*** Translator Repeat {0}", id));
}

}

}
}
}
catch { }
}
catch { }
}

public void AddExcludedControls(string [] s)
{
ExcludedControls.AddRange(s);
}

static public List<string> Languages(string txfolder)
static public List<string> Languages(string txfolder, bool nameonly)
{
FileInfo[] allFiles = Directory.EnumerateFiles(txfolder, "*.tlf", SearchOption.TopDirectoryOnly).Select(f => new FileInfo(f)).OrderBy(p => p.LastWriteTime).ToArray();

return allFiles.Select(x => Path.GetFileNameWithoutExtension(x.Name)).ToList();
return nameonly ? allFiles.Select(x => Path.GetFileNameWithoutExtension(x.Name)).ToList() : allFiles.Select(x => x.Name).ToList();
}

static public string FindLanguage(List<string> lang, string isoname)
static public string FindLanguage(List<string> lang, string isoname) // take filename part only, see if filename text-<iso> is present
{
return lang.Find(x =>
{
string filename = Path.GetFileNameWithoutExtension(x);
int dash = x.IndexOf('-');
return dash != -1 && x.Substring(dash + 1).Equals(isoname);
});
}

public string Translate(string normal, string id)
{
string key = id.ToLower();
if (translations != null && !normal.Equals("<code>") )
{
string key = id;
if (translations.ContainsKey(key))
{
//System.Diagnostics.Debug.WriteLine("Translate: \"{0}\" => \"{1}\"", id, translations[id]);
return translations[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;
}
Expand Down
9 changes: 5 additions & 4 deletions EDDiscovery/EDDOptions.cs
Expand Up @@ -29,7 +29,7 @@ public static EDDOptions Instance
public string UserDatabasePath { get; private set; }
public string SystemDatabasePath { get; private set; }
public string IconsPath { get; private set; }
public bool NoWindowReposition { get; set; }
public bool NoWindowReposition { get; set; }
public bool ActionButton { get; private set; }
public bool NoLoad { get; private set; }
public bool NoTheme { get; set; }
Expand Down Expand Up @@ -66,6 +66,7 @@ public static EDDOptions Instance
public string ThemeAppDirectory() { return SubAppDirectory("Theme"); }
public string DLLAppDirectory() { return SubAppDirectory("DLL"); }
public string TranslatorDirectory() { return SubAppDirectory("Translator"); }
static public string ExeDirectory() { return System.AppDomain.CurrentDomain.BaseDirectory; }

private string AppFolder { get; set; } // internal to use.. for -appfolder option
private bool StoreDataInProgramDirectory { get; set; } // internal to us, to indicate portable
Expand Down Expand Up @@ -97,7 +98,7 @@ private void SetAppDataDirectory()
}
else if (StoreDataInProgramDirectory)
{
AppDataDirectory = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, appfolder);
AppDataDirectory = Path.Combine(ExeDirectory(), appfolder);
}
else
{
Expand Down Expand Up @@ -286,9 +287,9 @@ public void Init()
{
ProcessConfigVariables();

ProcessOptionsFileOption(System.AppDomain.CurrentDomain.BaseDirectory); // go thru the command line looking for -optionfile, use relative base dir
ProcessOptionsFileOption(ExeDirectory()); // go thru the command line looking for -optionfile, use relative base dir

string optval = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "options.txt"); // options in the base folder.
string optval = Path.Combine(ExeDirectory(), "options.txt"); // options in the base folder.
if (File.Exists(optval)) // try options.txt in the base folder..
ProcessOptionFile(optval);

Expand Down
2 changes: 1 addition & 1 deletion EDDiscovery/EDDiscoveryController.cs
Expand Up @@ -153,7 +153,7 @@ public EDDiscoveryController(Func<Color> getNormalTextColor, Func<Color> getHigh

string path = EDDOptions.Instance.IconsPath ?? (EDDOptions.Instance.IconsAppDirectory() + "\\*.zip");

Icons.IconSet.LoadIconPack(path, EDDOptions.Instance.AppDataDirectory, AppDomain.CurrentDomain.BaseDirectory);
Icons.IconSet.LoadIconPack(path, EDDOptions.Instance.AppDataDirectory, EDDOptions.ExeDirectory());
}

public void Init() // ED Discovery calls this during its init
Expand Down
4 changes: 2 additions & 2 deletions EDDiscovery/EDDiscoveryForm.cs
Expand Up @@ -151,7 +151,7 @@ public EDDiscoveryForm()

msg.Invoke("Modulating Shields");

BaseUtils.Translator.Instance.LoadTranslation(EDDConfig.Instance.Language, CultureInfo.CurrentUICulture, EDDOptions.Instance.TranslatorDirectory());
BaseUtils.Translator.Instance.LoadTranslation(EDDConfig.Instance.Language, CultureInfo.CurrentUICulture, EDDOptions.Instance.TranslatorDirectory(), EDDOptions.ExeDirectory());
BaseUtils.Translator.Instance.AddExcludedControls(new string[]
{ "ComboBoxCustom", "NumberBoxDouble", "NumberBoxLong", "VScrollBarCustom", // Controls not for translation..
"StatusStripCustom" , "RichTextBoxScroll","TextBoxBorder", "AutoCompleteTextBox", "DateTimePicker" , "NumericUpDownCustom" });
Expand Down Expand Up @@ -884,7 +884,7 @@ private void ReportSyncProgress(int percentComplete, string message)

private void buttonReloadActions_Click(object sender, EventArgs e)
{
BaseUtils.Translator.Instance.LoadTranslation(EDDConfig.Instance.Language, CultureInfo.CurrentUICulture, EDDOptions.Instance.TranslatorDirectory());
BaseUtils.Translator.Instance.LoadTranslation(EDDConfig.Instance.Language, CultureInfo.CurrentUICulture, EDDOptions.Instance.TranslatorDirectory(), EDDOptions.ExeDirectory());
actioncontroller.ReLoad();
actioncontroller.CheckWarn();
actioncontroller.onStartup();
Expand Down

0 comments on commit b70f462

Please sign in to comment.