mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-11-05 13:24:51 +01:00
Strip all comments from the C# sources
Removes every // and /// comment from the 28 .cs files, -1331 lines.
Done with a lexer rather than a regex: the sources carry plenty of // inside
string literals (@"//\$decor\b", the //$o trainset directives, sb.Append("// "),
"https://wiki.eu07.pl/") and those must survive. It tracks regular, verbatim and
interpolated strings, interpolation holes and char literals. Every file was
checked by comparing the sequence of string-literal characters before and after
the strip; all 28 match. BOMs preserved, blank-line runs collapsed to one.
Claude-Session: https://claude.ai/code/session_01HamVNWE9mwmz1vs2iEpNQq
This commit is contained in:
@@ -6,22 +6,8 @@ using System.Xml;
|
||||
|
||||
namespace StarterNG.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Loads UI translations from plain XML files shipped in a <c>lang/</c> folder next
|
||||
/// to the executable (instead of dictionaries compiled into the assembly). The files
|
||||
/// are parsed with <see cref="XmlReader"/>, which works under Native AOT — unlike the
|
||||
/// Avalonia XAML loader, which has no runtime parser in AOT builds.
|
||||
///
|
||||
/// File format (lang/en.xml):
|
||||
/// <code>
|
||||
/// <Language code="en" name="English">
|
||||
/// <String key="NavScenarios">Scenarios</String>
|
||||
/// </Language>
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public class LocalizationService : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>Folder holding the language files, resolved as starter/lang next to the executable.</summary>
|
||||
public static string LangDirectory =>
|
||||
Path.Combine(AppContext.BaseDirectory, "startercfg", "lang");
|
||||
|
||||
@@ -29,32 +15,17 @@ public class LocalizationService : INotifyPropertyChanged
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raised after a language file is loaded. XAML bindings refresh themselves
|
||||
/// through <see cref="PropertyChanged"/>; this is for captions that code
|
||||
/// builds once and has to build again.
|
||||
/// </summary>
|
||||
public event Action? LanguageChanged;
|
||||
|
||||
/// <summary>Display name of the active language (e.g. "English", "Polski").</summary>
|
||||
public string CurrentLanguage { get; private set; } = "English";
|
||||
|
||||
/// <summary>Short ISO code of the active language (e.g. "en", "pl").</summary>
|
||||
public string CurrentLangCode { get; private set; } = "en";
|
||||
|
||||
/// <summary>Indexer used by the XAML bindings: returns the key itself when missing.</summary>
|
||||
public string this[string key] =>
|
||||
_strings.TryGetValue(key, out var value) ? value : key;
|
||||
|
||||
/// <summary>
|
||||
/// Metadata for one discovered language file.
|
||||
/// </summary>
|
||||
public readonly record struct LanguageInfo(string Code, string Name, string Path);
|
||||
|
||||
/// <summary>
|
||||
/// Scans the lang/ folder and returns the header metadata of every *.xml file
|
||||
/// without loading all of its strings. Used to populate the language selector.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<LanguageInfo> AvailableLanguages()
|
||||
{
|
||||
var list = new List<LanguageInfo>();
|
||||
@@ -71,17 +42,12 @@ public class LocalizationService : INotifyPropertyChanged
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Skip malformed files rather than crashing the launcher.
|
||||
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the language whose code or display name matches <paramref name="codeOrName"/>.
|
||||
/// Falls back to English ("en") when no match is found. Returns the resolved
|
||||
/// display name so callers can keep their stored setting consistent.
|
||||
/// </summary>
|
||||
public string Load(string codeOrName)
|
||||
{
|
||||
var languages = AvailableLanguages();
|
||||
@@ -97,7 +63,6 @@ public class LocalizationService : INotifyPropertyChanged
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to English, then to whatever is available first.
|
||||
if (match is null)
|
||||
{
|
||||
foreach (var lang in languages)
|
||||
@@ -114,14 +79,12 @@ public class LocalizationService : INotifyPropertyChanged
|
||||
LoadFile(info.Path, info.Code, info.Name);
|
||||
else
|
||||
{
|
||||
// No files at all: keep keys visible instead of blank UI.
|
||||
|
||||
_strings = new Dictionary<string, string>();
|
||||
CurrentLangCode = "en";
|
||||
CurrentLanguage = "English";
|
||||
}
|
||||
|
||||
// "Item[]" is the indexer name bindings listen for; the empty name asks
|
||||
// every binding on this object to re-read.
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Item[]"));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));
|
||||
LanguageChanged?.Invoke();
|
||||
@@ -135,16 +98,12 @@ public class LocalizationService : INotifyPropertyChanged
|
||||
var settings = new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true };
|
||||
using var reader = XmlReader.Create(path, settings);
|
||||
|
||||
// NOTE: ReadElementContentAsString() already advances the reader past the
|
||||
// element's end tag onto the *next* node, so we must NOT call Read() again
|
||||
// in that case - doing so would skip every second <String> entry. We only
|
||||
// advance explicitly for nodes we don't consume here.
|
||||
while (!reader.EOF)
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element && reader.Name == "String")
|
||||
{
|
||||
var key = reader.GetAttribute("key");
|
||||
var value = reader.ReadElementContentAsString(); // advances the reader
|
||||
var value = reader.ReadElementContentAsString();
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
dict[key] = value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user