I18NCommander/I18N Commander/Processor/Generators/DotnetBigFile.cs
Thorsten Sommer 630f014c1a
Implemented the .NET generator
- Added .NET generator setting for the namespace to use
- Added .NET generator setting to choose the default culture
- Added get child section method to section processor
- Added util to convert any string to a verbatim string literal
- Removed redundant variables on exceptions
2022-10-30 15:49:22 +01:00

141 lines
7.5 KiB
C#

using System.Text;
using DataModel.Database;
namespace Processor.Generators;
public class DotnetBigFile : IGenerator
{
private static readonly List<string> CULTURE_CODES = new();
private static int DEFAULT_CULTURE_INDEX = -1;
public async Task GenerateAsync()
{
const string filename = "I18N.cs";
var destPath = await AppSettings.GetGeneratorDotnetDestinationPath();
destPath = Environment.ExpandEnvironmentVariables(destPath);
var pathFinal = Path.Join(destPath, filename);
var pathTemp = Path.Join(destPath, filename + ".gen");
if(File.Exists(pathTemp))
File.Delete(pathTemp);
CULTURE_CODES.Clear();
var cultures = await AppSettings.GetCultureInfos();
foreach (var (code, _) in cultures)
CULTURE_CODES.Add(code);
DEFAULT_CULTURE_INDEX = await AppSettings.GetGeneratorDotnetDefaultCultureIndex();
DEFAULT_CULTURE_INDEX -= 1; // 1-based to 0-based
try
{
await using var fileStream = new FileStream(pathTemp, FileMode.CreateNew, FileAccess.Write, FileShare.None);
await using var writer = new StreamWriter(fileStream, Encoding.UTF8);
await writer.WriteLineAsync($"namespace {await AppSettings.GetGeneratorDotnetNamespace()};");
await this.CreateStaticClass(writer, "I18N", 0, async (streamWriter, indention) =>
{
var indentionString = this.AddIndention(indention);
var buildTime = DateTime.UtcNow;
await writer.WriteLineAsync($"{indentionString}public static readonly string BUILD_TIME = \"{buildTime:yyyy.MM.dd HH:mm:ss}\";");
await writer.WriteLineAsync($"{indentionString}public static readonly long BUILD_TIME_TICKS = {buildTime.Ticks};");
await writer.WriteLineAsync();
await writer.WriteLineAsync($"{indentionString}private static int PREVIOUS_CULTURE = -1;");
// Go through the first layer of sections:
var sections = await SectionProcessor.LoadLayer(0);
foreach (var section in sections)
await this.TransformSection(writer, indention, section);
});
}
finally
{
if(new FileInfo(pathTemp).Length > 0)
{
if(File.Exists(pathFinal))
File.Delete(pathFinal);
File.Move(pathTemp, pathFinal);
}
}
}
private string AddIndention(int indention) => new string(' ', indention * 3);
private async Task TransformSection(TextWriter writer, int indention, Section section)
{
await this.CreateStaticClass(writer, section.DataKey, indention, async (_, innerIndention) =>
{
var textElements = section.TextElements;
foreach (var textElement in textElements)
await this.TransformTextElement(writer, innerIndention, textElement);
var childSections = await SectionProcessor.GetChildSections(section.DataKey);
foreach (var childSection in childSections)
await this.TransformSection(writer, innerIndention, childSection);
});
}
private async Task TransformTextElement(TextWriter writer, int indention, TextElement textElement)
{
var indentionString = this.AddIndention(indention);
var indentionPropString = this.AddIndention(indention + 1);
var indentionPropInner1String = this.AddIndention(indention + 2);
var indentionPropInner2String = this.AddIndention(indention + 3);
var indentionPropInner3String = this.AddIndention(indention + 4);
await writer.WriteLineAsync($"{indentionString}private static string E_{textElement.Code}_CACHE = \"\";");
await writer.WriteLineAsync($"{indentionString}public static string E_{textElement.Code}");
await writer.WriteLineAsync($"{indentionString}{{");
await writer.WriteLineAsync($"{indentionPropString}get");
await writer.WriteLineAsync($"{indentionPropString}{{");
await writer.WriteLineAsync($"{indentionPropInner1String}var currentCulture = CultureInfo.CurrentCulture.Name;");
await writer.WriteLineAsync($"{indentionPropInner1String}if(PREVIOUS_CULTURE == currentCulture.GetHashCode())");
await writer.WriteLineAsync($"{indentionPropInner2String}return E_{textElement.Code}_CACHE;");
await writer.WriteLineAsync($"{indentionPropInner1String}else");
await writer.WriteLineAsync($"{indentionPropInner1String}{{");
await writer.WriteLineAsync($"{indentionPropInner2String}PREVIOUS_CULTURE = currentCulture.GetHashCode();");
for (var cultureIndex = 0; cultureIndex < CULTURE_CODES.Count; cultureIndex++)
{
if(cultureIndex == 0)
await writer.WriteLineAsync($"{indentionPropInner2String}if (currentCulture.StartsWith(\"{CULTURE_CODES[cultureIndex]}\", StringComparison.InvariantCultureIgnoreCase))");
else
await writer.WriteLineAsync($"{indentionPropInner2String}else if (currentCulture.StartsWith(\"{CULTURE_CODES[cultureIndex]}\", StringComparison.InvariantCultureIgnoreCase))");
await writer.WriteLineAsync($"{indentionPropInner2String}{{");
var cultureTranslation = textElement.Translations.FirstOrDefault(x => x.Culture == CULTURE_CODES[cultureIndex]);
var cultureText = cultureTranslation?.Text ?? string.Empty;
await writer.WriteLineAsync($"{indentionPropInner3String}var text = @\"{Utils.MadeVerbatimStringLiteral(cultureText)}\";");
await writer.WriteLineAsync($"{indentionPropInner3String}E_{textElement.Code}_CACHE = text;");
await writer.WriteLineAsync($"{indentionPropInner3String}return text;");
await writer.WriteLineAsync($"{indentionPropInner2String}}}");
}
// Add the default case:
await writer.WriteLineAsync($"{indentionPropInner2String}else");
await writer.WriteLineAsync($"{indentionPropInner2String}{{");
var defaultCultureTranslation = textElement.Translations.FirstOrDefault(x => x.Culture == CULTURE_CODES[DEFAULT_CULTURE_INDEX]);
var defaultCultureText = defaultCultureTranslation?.Text ?? string.Empty;
await writer.WriteLineAsync($"{indentionPropInner3String}var text = @\"{Utils.MadeVerbatimStringLiteral(defaultCultureText)}\";");
await writer.WriteLineAsync($"{indentionPropInner3String}E_{textElement.Code}_CACHE = text;");
await writer.WriteLineAsync($"{indentionPropInner3String}return text;");
await writer.WriteLineAsync($"{indentionPropInner2String}}}");
await writer.WriteLineAsync($"{indentionPropInner1String}}}");
await writer.WriteLineAsync($"{indentionPropString}}}");
await writer.WriteLineAsync($"{indentionString}}}");
await writer.WriteLineAsync();
}
private async Task CreateStaticClass(TextWriter writer, string name, int indention, Func<TextWriter, int, Task> content)
{
var indentionString = this.AddIndention(indention);
await writer.WriteLineAsync(indentionString);
await writer.WriteLineAsync($"{indentionString}public static class {name}");
await writer.WriteLineAsync($"{indentionString}{{");
await content(writer, indention + 1);
await writer.WriteLineAsync($"{indentionString}}}");
}
}