mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 18:31:17 +03:00
119 lines
4.1 KiB
C#
119 lines
4.1 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.Encodings.Web;
|
|
using System.Text.Json;
|
|
using System.Text.RegularExpressions;
|
|
using Robust.Shared.ContentPack;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Content.Server.Corvax.GuideGenerator;
|
|
|
|
public static class LocJsonGenerator
|
|
{
|
|
private static readonly JsonSerializerOptions SerializeOptions = new()
|
|
{
|
|
WriteIndented = true,
|
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
|
};
|
|
|
|
// Matches top-level message/term identifiers at start of line (no leading whitespace or comment).
|
|
private static readonly Regex TopEntryRegex =
|
|
new(@"(?m)^(?!\s|#)([^\s=]+)\s*=", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
|
|
|
// Matches attribute lines like " .attr-name ="
|
|
private static readonly Regex AttrRegex =
|
|
new(@"(?m)^\s*\.(?<name>[A-Za-z0-9_\-]+)\s*=", RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
|
|
|
private static string GetStringSafe(string key)
|
|
{
|
|
try
|
|
{
|
|
return Loc.GetString(key);
|
|
}
|
|
catch
|
|
{
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public static void PublishJson(Stream stream)
|
|
{
|
|
var loc = IoCManager.Resolve<ILocalizationManager>();
|
|
var res = IoCManager.Resolve<IResourceManager>();
|
|
|
|
// Choose culture: default if set, otherwise first found culture.
|
|
var culture = loc.DefaultCulture ?? loc.GetFoundCultures().FirstOrDefault();
|
|
if (culture == null)
|
|
{
|
|
JsonSerializer.Serialize(stream, new Dictionary<string, object?>(), SerializeOptions);
|
|
return;
|
|
}
|
|
|
|
var root = new ResPath($"/Locale/{culture.Name}");
|
|
var files = res.ContentFindFiles(root)
|
|
.Where(c => c.Filename.EndsWith(".ftl", StringComparison.InvariantCultureIgnoreCase))
|
|
.ToArray();
|
|
var keys = new Dictionary<string, HashSet<string>>();
|
|
|
|
foreach (var path in files)
|
|
{
|
|
using var fileStream = res.ContentFileRead(path);
|
|
using var reader = new StreamReader(fileStream, Encoding.UTF8);
|
|
var contents = reader.ReadToEnd();
|
|
// Normalize line endings to simplify indexing.
|
|
contents = contents.Replace("\r\n", "\n");
|
|
|
|
var matches = TopEntryRegex.Matches(contents);
|
|
for (var mi = 0; mi < matches.Count; mi++)
|
|
{
|
|
var m = matches[mi];
|
|
var id = m.Groups[1].Value.Trim();
|
|
if (string.IsNullOrEmpty(id))
|
|
continue;
|
|
|
|
if (!keys.ContainsKey(id))
|
|
keys[id] = new HashSet<string>();
|
|
|
|
var start = m.Index;
|
|
var end = mi + 1 < matches.Count ? matches[mi + 1].Index : contents.Length;
|
|
var block = contents.Substring(start, end - start);
|
|
|
|
var attrMatches = AttrRegex.Matches(block);
|
|
foreach (Match am in attrMatches)
|
|
{
|
|
var attrName = am.Groups["name"].Value;
|
|
if (!string.IsNullOrEmpty(attrName))
|
|
keys[id].Add(attrName);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Build JSON dictionary using Loc.GetString for main key and for attributes.
|
|
var output = new Dictionary<string, object?>();
|
|
foreach (var (id, attrs) in keys.OrderBy(k => k.Key))
|
|
{
|
|
if (attrs.Count == 0)
|
|
{
|
|
output[id] = GetStringSafe(id);
|
|
}
|
|
else
|
|
{
|
|
// _value is the main value of the key.
|
|
var obj = new Dictionary<string, string?>
|
|
{
|
|
["_value"] = GetStringSafe(id),
|
|
};
|
|
foreach (var attr in attrs.OrderBy(a => a))
|
|
{
|
|
var value = GetStringSafe($"{id}.{attr}");
|
|
if (!string.IsNullOrEmpty(value))
|
|
obj[attr] = value;
|
|
}
|
|
output[id] = obj;
|
|
}
|
|
}
|
|
|
|
JsonSerializer.Serialize(stream, output, SerializeOptions);
|
|
}
|
|
}
|