nerushfgbhjkze4ghbieurzdh789izouehzbugk4789ziogh

This commit is contained in:
Mira 2024-01-20 13:52:52 +01:00
parent 8f4df05ac8
commit d2f03874f5
Signed by untrusted user who does not match committer: Xorog
GPG key ID: 983798ED9C3E7C36
11 changed files with 451 additions and 0 deletions

View file

@ -0,0 +1,295 @@
// Project Makoto
// Copyright (C) 2023 Fortunevale
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
global using Xorog.Logger;
global using Xorog.UniversalExtensions;
global using Xorog.UniversalExtensions.Entities;
global using static TranslationSourceGenerator.Log;
global using static Xorog.UniversalExtensions.UniversalExtensions;
global using Newtonsoft.Json;
using System.Reflection;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
namespace TranslationSourceGenerator;
internal class Program
{
public string MakotoSourceOrigin => $@"
// Project Makoto
// Copyright (C) 2023 Fortunevale
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
namespace {this.Namespace};
#pragma warning disable CS8981
#pragma warning disable CS8618
#pragma warning disable IDE1006
public class Translations : ITranslations
{{
public Dictionary<string, int> Progress = new();
public CommandTranslation[] CommandList {{ get; set; }}
#region AutoGenerated
// InsertPoint
#endregion AutoGenerated
}}
";
public string StringsJson { get; set; }
public string TranslationCs { get; set; }
public string Namespace { get; set; }
static void Main(string[] args)
=> new Program().Execute(args).GetAwaiter().GetResult();
public async Task Execute(string[] args)
{
if (!Directory.Exists($"{new FileInfo(Assembly.GetExecutingAssembly().FullName).Directory.FullName}/logs"))
_ = Directory.CreateDirectory($"{new FileInfo(Assembly.GetExecutingAssembly().FullName).Directory.FullName}/logs");
_logger = LoggerClient.StartLogger($"{new FileInfo(Assembly.GetExecutingAssembly().FullName).Directory.FullName}/logs/{DateTime.UtcNow:dd-MM-yyyy_HH-mm-ss}.log", CustomLogLevel.Debug, DateTime.UtcNow.AddDays(-3), false);
_ = Task.Run(async () =>
{
if (!File.Exists(args.Length > 0 ? args[0] : "e252zru2rjb2rtb23jbrj2bthj2bthjb2jtb4jbtb2jtb4hj"))
{
_logger.LogError("Translation json expected as arg0");
return;
}
if (!File.Exists(args.Length > 1 ? args[1] : "e252zru2rjb2rtb23jbrj2bthj2bthjb2jtb4jbtb2jtb4hj"))
{
_logger.LogError("Translation json expected as arg1");
return;
}
if (args.Length < 2)
{
_logger.LogError("Namespace expected as arg2");
return;
}
this.StringsJson = args[0];
this.TranslationCs = args[1];
this.Namespace = args[2];
_logger.LogDebug("Project Makoto Translation Source Generator started up.");
_logger.LogDebug("Strings.json Location: {0}", Path.GetFullPath(this.StringsJson));
_logger.LogDebug("Translation.cs Location: {0}", Path.GetFullPath(this.TranslationCs));
DateTime lastModify = new();
while (true)
{
try
{
Dictionary<string, List<string>> addedFields = new();
FileInfo fileInfo = new(this.StringsJson);
if (lastModify != fileInfo.LastWriteTimeUtc)
{
try
{
List<string> Warnings = new();
var Insert = "";
_logger.LogDebug("Translation file updated. Updating Translations.cs..");
var jsonFile = (JObject)JsonConvert.DeserializeObject(File.ReadAllText(this.StringsJson));
string CreateValidValueName(string str)
=> Regex.Replace(str, @"[^a-zA-Z0-9]", "_");
void RecursiveHandle(JObject token, string ParentPath, int depth)
{
foreach (var item in token)
{
var className = CreateValidValueName($"{item.Key.First().ToString().ToLower()}{item.Key.Remove(0, 1)}");
switch (className)
{
case "object":
className = $"@{className}";
break;
default:
break;
}
var fieldName = CreateValidValueName(item.Key.FirstLetterToUpper());
var entryPoint = $"{ParentPath}/{className}";
var IndexPath = $"// {ParentPath} InsertPoint";
var InsertPosition = 0;
if (!ParentPath.IsNullOrWhiteSpace())
{
InsertPosition = Insert.IndexOf(IndexPath) + IndexPath.Length;
}
if (!addedFields.ContainsKey(IndexPath))
addedFields.Add(IndexPath, new());
switch (item.Value.Type)
{
case JTokenType.Object:
{
var containsLocaleCode = false;
var localeCodeIsArray = false;
List<KeyValuePair<string, JToken?>> tokens = new();
foreach (var subItem in item.Value.ToObject<JObject>())
{
tokens.Add(subItem);
if (subItem.Key == "en")
{
containsLocaleCode = true;
localeCodeIsArray = subItem.Value.Type == JTokenType.Array;
}
}
if (containsLocaleCode)
{
if (!localeCodeIsArray)
{
var line = $"{new string(' ', depth * 4)}public SingleTranslationKey {CreateValidValueName(item.Key)};";
if (addedFields[IndexPath].Contains(line))
continue;
_logger.LogDebug("Found SingleKey '{0}'", item.Key);
Insert = Insert.Insert(InsertPosition, $"\n{line}");
addedFields[IndexPath].Add(line);
if (!tokens.Any(x => x.Key == "de"))
Warnings.Add($"String at path {entryPoint} has no de translation");
}
else
{
var line = $"{new string(' ', depth * 4)}public MultiTranslationKey {CreateValidValueName(item.Key)};";
if (addedFields[IndexPath].Contains(line))
continue;
_logger.LogDebug("Found MultiKey '{0}'", item.Key);
Insert = Insert.Insert(InsertPosition, $"\n{line}");
addedFields[IndexPath].Add(line);
if (!tokens.Any(x => x.Key == "de"))
Warnings.Add($"String at path {entryPoint} has no de translation");
}
continue;
}
else
{
_logger.LogDebug("Found Group '{0}'", item.Key);
var line = $"\n{new string(' ', depth * 4)}public {className} {fieldName};\n" +
$"{new string(' ', depth * 4)}public sealed class {className}\n" +
$"{new string(' ', depth * 4)}{{\n" +
$"{new string(' ', depth * 4)}// {entryPoint} InsertPoint\n" +
$"{new string(' ', depth * 4)}}}\n";
if (addedFields[IndexPath].Contains(line))
break;
Insert = Insert.Insert(InsertPosition, line);
addedFields[IndexPath].Add(line);
}
RecursiveHandle(item.Value.ToObject<JObject>(), entryPoint, depth + 1);
break;
}
case JTokenType.Integer:
{
_logger.LogDebug("Found Int '{0}'", item.Key);
var line = $"\n{new string(' ', depth * 4)}public int {CreateValidValueName(item.Key)};";
if (addedFields[IndexPath].Contains(line))
continue;
Insert = Insert.Insert(InsertPosition, line);
addedFields[IndexPath].Add(line);
break;
}
case JTokenType.Array:
{
_logger.LogDebug("Found Array '{0}'", item.Key);
var line = $"\n{new string(' ', depth * 4)}public {className}[] {fieldName};\n" +
$"{new string(' ', depth * 4)}public sealed class {className}\n" +
$"{new string(' ', depth * 4)}{{\n" +
$"{new string(' ', depth * 4)}// {entryPoint} InsertPoint\n" +
$"{new string(' ', depth * 4)}}}\n";
if (fieldName == "CommandList" && IndexPath == "// InsertPoint")
{
continue;
}
if (!addedFields[IndexPath].Contains(line))
{
Insert = Insert.Insert(InsertPosition, line);
addedFields[IndexPath].Add(line);
}
foreach (var b in item.Value.ToObject<JArray>())
RecursiveHandle(b.ToObject<JObject>(), entryPoint, depth + 1);
break;
}
default:
break;
}
}
}
RecursiveHandle(jsonFile, "", 1);
foreach (var b in Warnings)
{
_logger.LogWarn(b);
}
_logger.LogWarn("Source Generation finished with {Count} warnings.", Warnings.Count);
Insert = string.Join("\n", Insert.Split("\n").Where(x => !x.Contains("InsertPoint")));
File.WriteAllText(this.TranslationCs, string.Join("\n", this.MakotoSourceOrigin.Replace("// InsertPoint", Insert).ReplaceLineEndings("\n").Split("\n", StringSplitOptions.RemoveEmptyEntries).Where(x => !x.IsNullOrWhiteSpace())));
_logger.LogDebug("Updated Translations.cs.");
}
catch (Exception ex)
{
_logger.LogError("Failed to update Translations.cs.", ex);
}
}
lastModify = fileInfo.LastWriteTimeUtc;
await Task.Delay(1000);
}
catch (Exception ex)
{
_logger.LogError("Failed to watch file", ex);
await Task.Delay(10000);
}
}
});
await Task.Delay(-1);
}
}